home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / basic / glib19.zip / GLIB19.DOC < prev    next >
Text File  |  1991-06-27  |  204KB  |  5,480 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.                                 GLIB version 1.90
  9.                               Released: June, 1991
  10.                        Copyright InfoSoft, 1986-1990, 1991
  11.  
  12.                 Note: This release is intended for QB 4.5 ONLY !
  13.                     For BASIC PDS 7.x support, get GLib 2.01x
  14.  
  15.  
  16.  
  17.          The files that should be included on this disk or .ZIP are:
  18.  
  19.          GLIB19.NEW    - Overview of new features in GLib 1.9
  20.          GLIB19.DOC    - Complete Library documentation.
  21.          MACRO19.DOC   -  Documentation for care and feeding of the        
  22.                          Macro Field Editor, QCalc, Clock, DialogBox       
  23.                          and Status Line 'macro' Routines.
  24.          GLIBXTD.BI    - BASIC include file of declarations for ALL
  25.                          GLib 1.9 routines (for reference use).
  26.          GLIB19.QLB    - The routines for use with QB4 environment.
  27.          GLIBDEMO.BAS  - A QB demo of some of the routines.
  28.          QCALCDEM.BAS  - Brief demo of the QCALC routine.
  29.          MFEDDEMO.BAS  - Demo of MFed, text input handler.
  30.          EMP.DAT       - Sample data file for MFEDDEMO.BAS
  31.          MAILERG       - Quick Mailer for registering.
  32.          LIST.ME       - Any last minute thoughts or notes
  33.  
  34.  
  35.  
  36.          Upon registering, users  will also receive a Quick Reference guide
  37.      to using the routines (GLIB19.QRF).
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.                    Copyright (C) InfoSoft, 1986-1990, 1991                1
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.          License, Terms and Use:
  73.                                 
  74.             Under  no  circumstances  may  these  routines  be  distributed
  75.      individually or without  the accompanying  documentation, which is  an
  76.      integral part of the package, nor may the documentation  be altered in
  77.      anyway.  This includes, but is  not limited to distributing GLIB19.QLB
  78.      for use in executing applications compiled to BRUN format.
  79.  
  80.             Under no  circumstances may the  routines in the  GLIB package,
  81.      source, object files, libraries or documentation  be distributed by or
  82.      otherwise  become  a  part  of,  or   affiliated  with  any  group  or
  83.      organization  involved in the  distribution of what  is generally been
  84.      come to be  known as SHAREWARE for  disk or distribution fees,  or for
  85.      fees of  any sort without my  express WRITTEN consent.   This includes
  86.      supplying the  routines, library  and or  documentation for  so-called
  87.      disk fees.
  88.  
  89.             Finally, we make  no claims that  the routines herein will  fit
  90.      your needs, simply that in all testing  and prior use that they worked
  91.      for  us and  that you may  find them  interesting and helpful  in your
  92.      programming.   Any liability  for the use, misuse  or inability to use
  93.      the GLIB routines or libraries, is solely the users.
  94.  
  95.  
  96.  
  97.                        
  98.          1.   GLIB  Compatibility
  99.             Unless otherwise noted, all  routines used in GLIB  are written
  100.      in assembler with MASM 5.1.   The few BASIC based routines that  there
  101.      are, were written under QB 4.5 or the MS BASIC PDS Compiler 7.x.
  102.  
  103.              DO  NOT  attempt  to  combine older  QB3  routines  with  QB4x
  104.      routines into  a QB4 compiled program or  library.  ASM based routines
  105.      require significant conversion for use under QB4.  Linking QB3 and QB4
  106.      BASIC based routines will  require that both runtime modules  be used,
  107.      BCOM/BRUN30 and BCOM/BRUN40 - which WILL yield certain disaster.
  108.  
  109.  
  110.  
  111.          2.    Support
  112.             As long as  it exists, I  will support and entertain  questions
  113.      regarding  QB  and/or  GLIB   via  the  QuickBASIC  conference on  The
  114.      Information Booth, (316) 684 8744, 1200 - 2400 bps, 24 hrs.
  115.             If  you have  a problem with  GLIB, you  _MUST_ be  prepared to
  116.      supply  supporting  source  code  demonstrating  the problem  you  are
  117.      having.  I am  more than a  little interested in any  GLib or QB  bugs
  118.      that you might find, but I do not have the time to track down problems
  119.      based on  vague descriptions of problems when I  cannot see if you are
  120.      using the sub  program right.  PLEASE  do not waste my  time with gen-
  121.      eral, vague inquiries  without supporting source  examples - I do  not
  122.      need and cannot use .EXE files.
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.                    Copyright (C) InfoSoft, 1986-1990, 1991                2
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.          3.   Terms of usage
  140.             You are granted free and unlimited  personal use of any and all
  141.      routines in the environment library (".QLB") for GLIB 1.9 that you may
  142.      find of  value.   Furthermore,  you are  free to  pass  along the  BBS
  143.      distribution files (listed  at the start of this  document) as long as
  144.      they are  passed along as a  whole according to  the guidelines listed
  145.      above.
  146.             No one  is granted any  permission to  share or pass  along the
  147.      BCOM library (".LIB") or any object files.    As distributed, the GLIB
  148.      documentation,  demo  or tutor  and  the environment  library (".QLB")
  149.      provide you with everything you need to call and execute GLIB routines
  150.      from within the  editor/environment.  Furthermore, as  described above
  151.      you are  given unlimited rights  for such use.   This provides  an ex-
  152.      tremely generous forum for purposes  of sampling, testing and  evalua-
  153.      tion and allows  unlimited latitude in terms  of personal use or  as a
  154.      tutorial  regarding some  of  the more  advanced  features in  today's
  155.      QuickBASIC.  Note that this  personal use does not include  any rights
  156.      to  distribute the .QLB  as a runtime  module.  That  is, if your sole
  157.      intent with GLib  is personal use or experimental use  from within the
  158.      environment, no monies are requested, expected or solicited.
  159.  
  160.             However,  you might find some of the routines of value and want
  161.      to incorporate  them into  a standalone  .EXE applications.   In  this
  162.      case, the  library (.LIB) of  routines and  permission to use  them in
  163.      such applications may be purchased as described in item (4) below.
  164.  
  165.  
  166.          4.  License terms
  167.              If you  choose to  purchase a  LIBRARY/OBJECT module  license,
  168.      implicit in that, is  the specific rights to use the  routines in GLIB
  169.      in your standalone runtime program either by direct linking or the use
  170.      of the  BUILDRTM program  in  BASIC PDS.   This  further includes  the
  171.      supplying the QuickLibrary (QLB)  as a runtime module if  that is your
  172.      desire, however this method  does not either implicitly or  explicitly
  173.      bequeath another or secondary LIBRARY/OBJECT module license to any end
  174.      user(s) or people receiving  that as a run time module.   The routines
  175.      may only be passed along  in linked form, as a QLB or  EXE file, never
  176.      as an OBJECT module or in LIBRARY form.
  177.  
  178.             A LIBRARY/OBJECT module license is grated only to the person or
  179.      company providing payment  or named  on the mailer.   No  grandfather,
  180.      parent or  child usage  rights are  implied or  granted.   That is,  a
  181.      LIBRARY license  purchased by  an individual  grant the  usage of  the
  182.      library by that individual,  not their employer or anyone  outside the
  183.      immediate  family.   Conversely,  a  license purchased  by  a company,
  184.      corporation, business  or government  organization does  not imply  or
  185.      grant any person employed, allied or associated with that organization
  186.      personal usage rights without purchasing a LIBRARY/OBJECT license.
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.                    Copyright (C) InfoSoft, 1986-1990, 1991                3
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.          5.  Purchasing GLIB
  206.  
  207.             To get the  latest version of  GLIB as  well as the  standalone
  208.      library (.LIB):
  209.  
  210.  
  211.           a. QB Version Support
  212.              We  will  no longer  compile  current  code for  all  previous
  213.      versions of QB.  The  chart below defines those GLib Libraries  avail-
  214.      able for the various QB version over the last few years.
  215.  
  216.                        QB 4.0     QB 4.00(a / b)    QB 4.5    BASIC PDS 7.x
  217.         GLib 2.0?/x                                                 X
  218.         GLib 1.9                                       X
  219.       **GLib 1.7         X              X
  220.  
  221.          ** Version 1.7 is a past release, but since it is the last to
  222.             support QB 4.0, QB 4.0(a), QB 4.00(b) and BASCOM 6.00, we will
  223.             continue to support it (and it alone) for those still using
  224.             those QB versions.
  225.  
  226.  
  227.           b. First Time buyers:
  228.              Fill out  the enclosed  mailer, with  $40 in  checks or  money
  229.      orders (these must be payable in US Funds)  and mail it to the address
  230.      on  the mailer.  You'll receive,  by return mail a diskette containing
  231.      complete documentation, object files, .LIB and .QLB for release 1.9.
  232.  
  233.  
  234.  
  235.           c. Upgrading a previous GLib version:
  236.              Upgrades from GLib 1.7 with your serial number are $15.00 
  237.              Upgrades from GLib 1.7 without serial number,
  238.                    as well as GLib version 1.6/1.65 are $20.00
  239.              Upgrades from GLib 1.5 and before are $30.00
  240.            
  241.              Fill out the mailer, indicating an upgrade and the version
  242.      originally purchased and send  it back with  US Funds, and we'll  mail
  243.      out an upgrade diskette.
  244.  
  245.  
  246.  
  247.           d. In ALL cases, you MUST use  the mailer so that we can identify
  248.      diskette type, QB version etc.  Please allow 4-5 weeks for delivery.
  249.  
  250.  
  251.          Mailing Address:
  252.                                       InfoSoft
  253.                                       GLIB 1.9
  254.                                    PO Box 782057
  255.                                      Wichita, Ks
  256.                                             67278-2057
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.                    Copyright (C) InfoSoft, 1986-1990, 1991                4
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.                             GLIB 1.9 Functions and Sub Programs
  272.                             -----------------------------------
  273.  
  274.          NOTE WELL:   All but a very,  very few GLib functions  are in ass-
  275.      embler.  As  such, the data type you  pass is VERY important.   Unless
  276.      otherwise specified, all  numbers are INTEGERS,  so assume a  trailing
  277.      '%' unless otherwise noted.   This pertains to  FUNCTIONS too:   Ansi-
  278.      Loaded is  AnsiLoaded% unless  DEFINT A-Z  is in  effect.    Likewise,
  279.      string lengths can  be critical and care  should be taken to  note and
  280.      pass the required length for correct results.
  281.  
  282.  
  283.  
  284.              Name: AnsiLoaded               Type: FUNCTION
  285.          Syntax: RCode = AnsiLoaded
  286.  
  287.          This  simply  returns  an  integer   indicating  is  ANSI.SYS  (or
  288.      compatible) is loaded as  a device driver.  If loaded,  it returns non
  289.      Zero and  if not, it  returns zero.   This can helpful  in determining
  290.      whether to use DPRINT (qv) or not.
  291.  
  292.  
  293.  
  294.              Name: ArgCnt                   Type: FUNCTION
  295.          Syntax: qargs = ArgCnt
  296.          ArgCnt may also be invoked with the 'C' like name of 'argc'.
  297.  
  298.          Returns the number of arguments in the command tail delimited by a
  299.      space.   That is, with  'FOOBAR.EXE /qwerty /1 /2 /3 /4', ArgCnt would
  300.      return 5 as the number of command  tail arguments.  ArgCnt can also be
  301.      called by the  'C'-like name of argc.  See also ArgVar and GetCmdTail.
  302.      ArgVar and ArgCnt replace the interim routine CmdLine.  Example:
  303.          PRINT "Number of command line arguments is: "; ArgCnt
  304.  
  305.  
  306.  
  307.              Name: ArgVar                   Type: FUNCTION
  308.          Syntax: var$ = ArgVar$(arg)
  309.          ArgVar may also be invoked with the 'C' like name of 'argv'.
  310.  
  311.          ArgVar is the complementary routine  to ArgCnt(qv) by returning  a
  312.      specified argument from the command tail in the  programs PSP.  ArgVar
  313.      returns a string  variable representing the unparsed,  specified argu-
  314.      ment from  the command  tail.  To  fetch the  entire command  tail see
  315.      GetCmdTail.    As  with ArgCnt and  GetCmdTail, ArgVar deals  with the
  316.      ACTUAL  command tail  found  in the  program's PSP,  so accommodations
  317.      should be made for when your program  running as a QB file versus as a
  318.      EXE (see QBLoaded).  Example - Print all command tail elements:
  319.          FOR x = 1 to argc
  320.              PRINT argv$(x)               ' prints them one-by-one
  321.          NEXT x
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.                    Copyright (C) InfoSoft, 1986-1990, 1991                5
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.              Name: AttrMake                 Type: FUNCTION
  337.          Syntax: attr = AttrMake(Fg, Bg)
  338.  
  339.          Converts 2 integers  representing the  fore and background  colors
  340.      into a single integer representing the attribute.    Example:
  341.          Attr = AttrMake(14, 4)              ' returns 78
  342.  
  343.  
  344.  
  345.              Name: AttrRev                  Type: FUNCTION
  346.          Syntax: NewAttr = AttrRev(Attr)
  347.  
  348.          Reverses  a  passed attribute  byte  from  fg/bg to  bg/fg.   When
  349.      highlighting a portion of the screen, this can be faster than separate
  350.      steps:
  351.          CALL AttrSplit(attr, fg, bg)     \ 
  352.          SWAP fg, bg                       >   NewAttr = AttrRev(attr)
  353.          NewAttr = AttrMake(fg, bg)       /
  354.  
  355.  
  356.              Name: AttrSplit                Type: SUB
  357.          Syntax: CALL AttrSplit(Attr, Fg, Bg)
  358.  
  359.          UnConverts  a  single integer  representing  the attribute  into 2
  360.      integers representing the fore and background  colors.  This assumes a
  361.      legitimate attribute value.  Example:
  362.          CALL AttrSplit(78, fg, bg)          ' fg = 14, bg=4
  363.  
  364.  
  365.  
  366.              Name: BCD2Int / Int2BCD        Type: FUNCTION
  367.          Syntax: IntVal = BCD2Int(BCDVal)
  368.                  BCDVal = Int2BCD(IntVal)
  369.  
  370.          Many times when dealing  with DOS directly, you need  Binary Coded
  371.      Decimal values  (such as  when tinkering  with DOS  file dates  and/or
  372.      times).  These 2  routines allows you to quickly encode  or decode BCD
  373.      values.
  374.  
  375.  
  376.              Name: BitChkInt/BitClrInt/BitSetInt  Type: FUNCTION
  377.          Syntax: result = BitChkInt(IValue, bit)
  378.                  result = BitClrInt(IValue, bit)
  379.                  result = BitSetInt(IValue, bit)
  380.  
  381.          Allows you to  CHECK, CLEAR or  SET a specific  bit in an  integer
  382.      value.  Such  integer bit coding allows you to store several values or
  383.      flags in  a single integer.   Since  an integer is  16 bits, up  to 16
  384.      different flags or  other 0/1 values  could be stored  on disk in  the
  385.      space of  2  bytes.   See also  Bit---Lng.   Note  that BitClrLng  and
  386.      BitSetLng both return new integers representing the new value with the
  387.      desired bits cleared or set.
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.                    Copyright (C) InfoSoft, 1986-1990, 1991                6
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.              Name: BitChkLng/BitClrLng/BitSetLng  Type: FUNCTION
  403.          Syntax: result& = BitChkLng(LValue&, bit)
  404.                  result& = BitClrLng&(LValue&, bit)
  405.                  result& = BitSetLng&(LValue&, bit)
  406.  
  407.          Allows  you to  CHECK, CLEAR  or  SET a  specific bit  in  an long
  408.      value.Long integer bit coding allows you to store up various values or
  409.      flags in a long integer. Since  a long  integer is  32 bits, up  to 32
  410.      different  flags or other  0/1 values could  be stored on  disk in the
  411.      space of 4 bytes. See also Bit---Int.  Note that BitClrLng and 
  412.      BitSetLng both  return new long  integers representing  the new  value
  413.      with the desired bits cleared or set.
  414.  
  415.  
  416.  
  417.              Name: Boxes                    Type: SUB
  418.          Syntax: CALL Boxes(TRow, LCol, BRow, LCol, frame, attr)
  419.  
  420.          BOXES is similar  to the windows  sub in that  it puts frame  like
  421.      items on  the screen.   BOXES  differs from  WINDOWS in  that a  wider
  422.      selection of frame styles are offered, fewer parameters are passed and
  423.      without the label  centering code, sound  effects and the like,  it is
  424.      slightly  faster.  The first four parameters mark the perimeter of the
  425.      box  to draw and  'attr' indicates the  color attribute to  use on the
  426.      frame and interior.   The frame  parameter may  range from 0  to 9  to
  427.      indicate the style of frame to use:
  428.               0 - Spaces used as border       
  429.               1 - Double / Double ( )         
  430.               2 - Double Horz / Single Vert ( )
  431.               3 - Single / Single ( )
  432.               4 - Single Horz / Double Vert ( )
  433.               5 - Medium Thick boxes (ASCII 220-223)
  434.               6 - thick boxes (ASCII 219, 219, 221, 222
  435.               7 - ASCII 176 used
  436.               8 - ASCII 177 used
  437.               9 - ASCII 178 used
  438.  
  439.  
  440.              Name: BoxesFrame               Type: SUB
  441.          Syntax: CALL BoxesFrame(TRow, LCol, BRow, LCol, frame, attr)
  442.  
  443.           BoxesFrame is almost identical to Boxes except  that the interior
  444.      is  hollow.   This allows  you to  pop a box  onto the  screen framing
  445.      existing text without disturbing that text.
  446.  
  447.  
  448.  
  449.              Name: BShadow                  Type: SUB
  450.           Syntax: CALL BShadow( 0 | 1 )
  451.           
  452.           This is used to indicate to the Library that all subsequent calls
  453.      to Boxes should automatically include a 3-D shadow effect.  Calling it
  454.      with a non  zero (1) parameter turns  on shading, while zero  turns it
  455.      off.   Use this  to also control  the shading effect  in FlexMenu (aka
  456.      MenuChoice).  Do  not confuse  this with WShadow  which control  which
  457.      SIDE the windows shadowing takes place on.
  458.  
  459.  
  460.  
  461.                    Copyright (C) InfoSoft, 1986-1990, 1991                7
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.              Name: BufferCalc               Type: FUNCTION
  469.          Syntax: size = BufferCalc(Trow, LCol, Brow, Rcol)
  470.  
  471.          Given a set of coordinates, BufferCalc returns an integer indicat-
  472.      ing the number of bytes indicating the  size an array would have to be
  473.      to hold such  a section of the  screen.  This can be  very useful when
  474.      used to size an array for use with SaveWdw - RestWdw.   Example:
  475.          size = BufferCalc(1, 1, 12, 40)
  476.          REDIM ScrnArry(size)
  477.          CALL SaveWindow(ScrnArry(1), 1, 1, 12, 40)
  478.  
  479.  
  480.                       
  481.              Name: Chirp                    Type: SUB
  482.          Syntax: CALL Chirp(x)
  483.  
  484.          This routine is used to sound the speaker in a fast tone of either
  485.      ascending or descending pitch.  The same method is used in WDW to make
  486.      the popping sound.  CHIRP is provided to allow you to make a un-
  487.      popping sound when removing a window.    There are 2 modes in the CHRP
  488.      routine:
  489.          mode 1 = ascending frequency (up)
  490.               2 = descending frequency (down)
  491.          Example:
  492.          m=1
  493.          CALL CHIRP(m)  ' will sound a "chirp" of ascending frequency      
  494.                   '   as will:
  495.          CALL CHIRP(1)
  496.  
  497.  
  498.  
  499.              Name: Chk286                 Type: FUNCTION
  500.          Syntax: retc = Chk286
  501.  
  502.          Provides  a quick  check as  to whether  a 80286 processor  is in-
  503.      stalled in the machine.  This can help determine the speed  of certain
  504.      loops in games  or other timing  dependant loops.   A non zero  return
  505.      indicates true, and zero  indicates false.  This is  called internally
  506.      by some GLib routines to check if a feature or function is systemical-
  507.      ly available.
  508.  
  509.  
  510.  
  511.              Name: CLon / CLoff             Type: SUB
  512.          Syntax: CALL CLON : CALL CLOFF
  513.  
  514.          Neither  of these  take an  argument or  pass a  parameter.   They
  515.      simply engage (CLON) or disengage (CLOFF) the Caps Lock state.
  516.  
  517.  
  518.              Name: Clock                    Type: SUB
  519.          Syntax: CALL Clock(Row, Col, Attr, Install)
  520.  
  521.          (CLOCK  is documented in  MACROxx.DOC).  Row and  Col are the (Tr,
  522.      Lc) coordinates for the display, attr is  the color to use and Install
  523.      is 0, 1 or 2 for Uninstall, Install or install quiet mode.
  524.  
  525.  
  526.  
  527.                    Copyright (C) InfoSoft, 1986-1990, 1991                8
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.              Name: ClrEOL                 Type: SUB
  535.          Syntax: CALL ClrEOL(row, col, attr%)
  536.  
  537.          Clears the video display  from the specified (row, col)  using the
  538.      specified attribute  to the End  Of the Line. See  also ClrSOL, ClrSOS
  539.      and ClrEOS.
  540.  
  541.  
  542.              Name: ClrEOS                 Type: SUB
  543.          Syntax: CALL ClrEOS(row, col, attr%)
  544.  
  545.          Clears the video display  from the specified (row, col)  using the
  546.      specified attribute to  the End Of the Screen. See also ClrSOL, ClrSOS
  547.      and ClrEOL.
  548.  
  549.  
  550.              Name: ClrSOL                 Type: SUB
  551.          Syntax: CALL ClrSOL(row, col, attr%)
  552.  
  553.          Clears the  specified line on the  video display from column  1 to
  554.      the specified  (row,  col) using  the  specified attribute.  See  also
  555.      ClrEOS,ClrSOS and ClrEOL.
  556.  
  557.  
  558.              Name: ClrSOS                 Type: SUB
  559.          Syntax: CALL ClrSOS(row, col, attr%)
  560.  
  561.          Clears the video display from Start of the Screen to the specified
  562.      (row, col) using the specified attribute. See also ClrEOS, ClrSOL and
  563.      ClrEOL.
  564.  
  565.  
  566.              Name: ClrKBD                   Type: SUB
  567.          Syntax: CALL ClrKBD
  568.  
  569.          Clear the keyboard buffer of any and all waiting keystrokes.  This
  570.      is an effective way of eliminating  type-ahead in critical portions of
  571.      your program.  See also KBStuff.
  572.  
  573.  
  574.  
  575.              Name: CPUInfo                  Type: FUNCTION
  576.          Syntax: support = CPUInfo(Model, SubModel, BiosRev,  CPUType,_    
  577.                       NDPType)
  578.  
  579.          This is a very  comprehensive system identification routine.   The
  580.      PC BIOS contains several bytes which can be used to determine the type
  581.      of PC it is and  whether it is a newer or later model.   If an earlier
  582.      PC  system does not support the  SubModel and BiosRev bytes, the func-
  583.      tion  will return  non zero in  support to  indicate this.   Most PC's
  584.      after 1984 will support this.
  585.  
  586.      This routine returns several things:
  587.          1) Model - This byte identifies the type or class of machine.  
  588.  
  589.          2) SubModel  -  This  identifies  similar type  systems  from  one
  590.      another, such as a Model 50 from a Model 60 or a 286 based system.
  591.  
  592.  
  593.                    Copyright (C) InfoSoft, 1986-1990, 1991                9
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.          3) BIOS Rev -  The BIOS Revision byte helps  further distinguishes
  601.      PC systems - such as the original IBM AT (6 Mhz) from the
  602.      later Model 339 (8 MHz).
  603.  
  604.  
  605.                                 PC Systems table:
  606.      Model  Sub Mod   BIOS rev
  607.      255      --        --       Orig. IBM PC type (all PC's to 10/82)
  608.      255      --        --       Original IBM XT's thru 8/82
  609.      255      --        --       Later IBM XT, XT/370 (11/82)
  610.  
  611.      254      --        --       XT, 3270PC, IBM Portables
  612.      251      00        01       XT's 1/10/1986
  613.      251      00        02       640 kb XT - 5/09/1986
  614.  
  615.      253      --        --       PCjr (6/1/83)
  616.  
  617.      252      --        --       IBM AT dated 1/10/84
  618.      252      00        01       286 Systems
  619.      252      01        00       286 Systems (ca 11/85)
  620.  
  621.      252      04        00       PS/2 Model 50
  622.      252      05        00       PS/2 Model 60
  623.      250*     00        00       PS/2 Model 30
  624.  
  625.      249      --        --       Convertible
  626.  
  627.      248      00        00       PS/2 Model 80
  628.  
  629.      Other
  630.      2d                          Compaq PC  4.77 (Mhz)
  631.      9a                          Compaq Plus (XT type)
  632.  
  633.          * We believe that the Model 25 shares this ID bytes with Model 30,
  634.      but has a different sub model or BIOS rev identifier.
  635.  
  636.  
  637.  
  638.  
  639.      4) CPU type installed, NDP type:
  640.      CPU returns  the significant  numbers in  the central  processor iden-
  641.      tification and NDP returns info on any numerical co-processor:
  642.      Type      CPU parameter                    Type       NDP parameter
  643.      ----      -------------                    ----       -------------
  644.      8086           86                          None            0
  645.      NEC V30        30                          8087            87
  646.      8088           88                          80287          287
  647.      NEC V20        20                          80387          387
  648.      80186          186
  649.      80188          188
  650.      80286          286
  651.      80386          386
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.                    Copyright (C) InfoSoft, 1986-1990, 1991               10
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.              Name: CRTSwap                  Type: SUB
  667.          Syntax: CALL CRTSwap(Crt, Mode)
  668.  
  669.             CRTSwap swaps  the primary  and alternate  display, making  the
  670.      primary display that indicated in the call.  This  means future QPRINT
  671.      and Save/RestoreScreen calls  will act  on the new  monitor.   BASIC's
  672.      PRINT will  continue to output to the initial display because QB, like
  673.      your programs, looks at the equipment  list only once at the start  of
  674.      the program and will not "notice" that you changed CRT's.   QPRINT and
  675.      other video routines like Save/Restore Screen determine the active CRT
  676.      each time  they are  called and  thus will  act upon  the new  primary
  677.      display.
  678.             When calling CRTSwap, you tell it which CRT to activate:
  679.          0 =  MONO, 1 =  CGA, 2= EGA/VGA.   Additionally, you  tell it what
  680.      video mode  to put it  in (not to  be confused  with the BASIC  SCREEN
  681.      function), by passing  the mode.  In  general, when making a  MONO CRT
  682.      the primary display, 7 is  the mode you will use, but CRTSwap  does no
  683.      checking for this.  In setting the new mode, the new primary screen is
  684.      inherently cleared.    Example:
  685.          CONST EGA = 3, MONO = 0     ' make MONO active in mode 7
  686.          CALL CRTSwap(MONO, 7)       ' PRINT to go to org display,         
  687.                             '  QPRINT to MDA
  688.          ..
  689.          ..
  690.          CALL CRTSwap(EGA, 3)        ' make EGA active in mode 3
  691.                                      ' PRINT goes to EGA, QPRINT to        
  692.                              '    EGA
  693.  
  694.  
  695.  
  696.  
  697.              Name: CtrlPrtSc         Type: SUB
  698.          Syntax: CALL CtrlPrtSc
  699.  
  700.          The  same  as  entering Ctrl-PrtSc  from  the  keyboard:  turns on
  701.      continuous printing.   Note that  this may  have no effect  on systems
  702.      with keyboard enhancers installed.
  703.  
  704.  
  705.  
  706.              Name: CvtAlt                 Type: FUNCTION
  707.          Syntax: retc = CvtAlt(x$)
  708.  
  709.          Returns  the ASCII  value of the  letter used  in with  an [Alt-?]
  710.      combination.  If  x$ is [Alt-Q], then  retv returns from CvtAlt  as 81
  711.      which is  ASC("Q").   This is  useful in  simplifying CASE  structures
  712.      which need to act on a wide variety of  input possibilities.  All such
  713.      [Alt-?]   key combinations  have a length  of 2  and CvtAlt  will only
  714.      attempt to    translate strings that  are 2 character long,  or CvtAlt
  715.      will return 0.
  716.  
  717.  
  718.              Name: Date                     Type: SUB
  719.          Syntax: CALL Date(mo, day, yr, dow)
  720.  
  721.          Return the current  system date information.   The day, month  and
  722.      year can be immediately used in DFRMAT.
  723.  
  724.  
  725.                    Copyright (C) InfoSoft, 1986-1990, 1991               11
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.              Name: DayOfYr                  Type: FUNCTION
  733.          Syntax: DaySoFar = DayOfYr
  734.  
  735.            This  simply  returns the  day of  year  as an  integer.   It is
  736.      accurate for  dates of 01-01-1980  to 02-28-2100 (The  year 2100  is a
  737.      centennial skip  leap year  - every 400  years we  skip a  leap year).
  738.      This is a FUNCTION that  works off the current system  date, returning
  739.      the day count in the FUNCTION name.    Example:
  740.          DECLARE FUNCTION DayOfYr%
  741.          .
  742.          .
  743.          TodayCount = DayOfYr
  744.  
  745.  
  746.  
  747.  
  748.              Name: DayOfWeek                Type: FUNCTION
  749.          Syntax: DCode = DayOfWeek(month, day, yr)
  750.          DayOfWeek can also be called as ZellerDay.
  751.  
  752.          This uses a modified form of  Zeller's Congruence to determine the
  753.      day of week for any valid date.  Example:
  754.  
  755.          WeekDay = ZellerDay(5, 17, 1989)      ' returns 3 for Wed
  756.  
  757.          PRINT "That was a "; DayName$(WeekDay)
  758.  
  759.  
  760.  
  761.         
  762.  
  763.              Name: Delay/Delay18            Type: SUB
  764.          Syntax: CALL Delay(secs)
  765.                  CALL Delay18(ticks)
  766.  
  767.          Delay will pause  a given number of  seconds to allow the  user to
  768.      read a display that you may have sent to the screen.  Delay18 allows a
  769.      delay resolution between  that of Delay  and MilliDelay by pausing  in
  770.      increments of 1 clock tick or 1/18.2th of a second.  Example:
  771.          sec=5
  772.          CALL Delay(sec)             ' or CALL Delay(5)
  773.          ..
  774.          CALL Delay18(9)             ' 1/2 second
  775.  
  776.  
  777.  
  778.  
  779.  
  780.              Name: DialogBox                Type: SUB
  781.          Syntax: CALL DialogBox(Msg$,  Prompt$, Ok$, Ret$)       (DialogBox
  782.      is fully documented in MACRO17.DOC).
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.                    Copyright (C) InfoSoft, 1986-1990, 1991               12
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.              Name: DFrmat                   Type: SUB     (BASIC)
  799.          Syntax: CALL DFrmat(m, d, y, nudate$)
  800.  
  801.          Passed  integers  for the  date,  this  routine will  pass  back a
  802.      formatted  date  string.   This  is  handy in  formatting  DOS/BASIC's
  803.      sterile date format into something that has a more pleasing on  screen
  804.      appearance.  The integers represent  the day, month and year,  and the
  805.      return is a string similar to "August 1, 1987".  
  806.  
  807.             DFRMAT has a  lower range  of 1800  as the year,  and any  year
  808.      passed  that is  lower than 1800  has 1900  added to it,  making 87 as
  809.      valid an argument as 1987.    Syntax:
  810.          CALL dfrmat(8, 1, 87, nudate$)
  811.          PRINT nudate$                   ' output is August 1, 1987
  812.  
  813.          Alternative:
  814.          CALL date(m, d, y, w)
  815.          CALL dfrmat(m, d, y, nudate$)
  816.  
  817.  
  818.  
  819.  
  820.              Name: DirA                     Type: FUNCTION
  821.          Syntax: errc = DirA(mask$, BYVAL VARPTR(fil$(1)))
  822.  
  823.          DirA replicates the  DOS DIR command  in an elegant and  efficient
  824.      method -  no shelling, no  reading the screen after  a FILES statement
  825.      and no loops to execute numerous calls to get files and their names.
  826.  
  827.          This is  similar to  the services  provided by  FirstF and  NextF,
  828.      except that it  places the returned file names directly  into a string
  829.      array.   If you need only a few names  or are searching for a specific
  830.      name FirstF and NextF  are ideal, but if you need to do something with
  831.      a file list, DirA is much faster and neater.  DirA works conventional 
  832.      string arrays (a  Fixed Length String version  is also included  - see
  833.      DirFLS)  - be sure  to initialize each  element to 12  or more spaces.
  834.      DirA returns just the file, not the pathname.  If less  than 12 spaces
  835.      are available, DirA  will supply as  much of  the name as  it can  and
  836.      return a -1  to indicate you  did not provide enough  space in one  or
  837.      more elements.
  838.  
  839.          Since DirA works with a string array, you can use FilCnt  first to
  840.      get the number of  files matching the mask ("*.*", "*.bas"  etc) so as
  841.      to dimension the array to the correct size.  If the array is too small
  842.      for the  number of matching  files and is  overrun, your program  will
  843.      surely crash.  (The array may be either Static or Dynamic).
  844.  
  845.          Note:  BASIC passes  parameters to  sub  programs by  passing it's
  846.      address.   However when passing a string array element, it first makes
  847.      a copy of  that element which  makes it impossible  to treat it as  an
  848.      array element.   By passing  the first element of the array BYVAL,  we
  849.      are able to pass  the address of the  actual starting point to  fil in
  850.      the array.  Because it is a FUNCTION and because it passes a parameter
  851.      BYVAL, DIRA MUST be declared.
  852.  
  853.  
  854.  
  855.  
  856.  
  857.                    Copyright (C) InfoSoft, 1986-1990, 1991               13
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.         Example:
  866.  
  867.          DECLARE FUNCTION DirA%(mask$, BYVAL ArryPtr%)
  868.          ..
  869.          errc = FilCnt("*.*", count)
  870.          REDIM Fil$(count)
  871.          FOR x = 1 to count
  872.              Fil$(x) = SPACE$(12)
  873.          NEXT x
  874.  
  875.          errc = DirA("*.*", VARPTR(Fil$(1)) )
  876.  
  877.  
  878.  
  879.  
  880.              Name: DirF                     Type: FUNCTION
  881.          Syntax: errc = DirF(mask$, SEG fil AS ANY)
  882.          Note: DirF may be invoked as either DirF or DirFLS
  883.  
  884.          When you create a standard string  array, what you actually create
  885.      is a table of string descriptors indicating the length and location of
  886.      each string element.   A fixed length  string array however is  a con-
  887.      tiguous  block  of string  memory with  no  descriptors.   Further, QB
  888.      passes a standard string array IMAGE of a fixed length string array to
  889.      subprograms,  so  a bit  of cleverness  is needed  to address  a Fixed
  890.      Length string  array - this  is done by  using the ANY  keyword in the
  891.      declaration statement.  According to Microsoft, the recommended way to
  892.      access  User Defined (TYPE) structures and  Fixed Length String Arrays
  893.      should be passed as a  segmented address and as ANY (SEG xxx  AS ANY).
  894.      Passing both the  segment and  address (VARSEG /  VARPTR) BYVAL  would
  895.      work because it is essentially  the same thing, but this is  certainly
  896.      messier.
  897.  
  898.          In the case of  DirFLS, we must use a fixed length  string that is
  899.      precisely  12 characters  per element.    Using 13  or 11  or  15 will
  900.      scramble the names due  to the contiguous nature of the  memory block.
  901.      Further,  since there are no descriptors  associated with Fixed length
  902.      Strings, the only error DirF will be able to detect is a NULL mask.
  903.          Example:
  904.          DECLARE SUB DirF (mask$, SEG arryptr AS ANY)
  905.          ..
  906.          ..
  907.          TYPE FStruct                   ' struct to hide FLS array in
  908.             s AS STRING * 12
  909.          END TYPE
  910.  
  911.          errc = FilCnt("*.*", count)       ' count files
  912.          DIM fil(count) AS STRING * 12     ' make Fixed Len array
  913.          CALL DirF(mask$, fil(1))          ' get dir list
  914.  
  915.          FOR x = 1 To count                ' print them - note the .s
  916.              PRINT fil(x).s
  917.          NEXT x
  918.  
  919.  
  920.  
  921.  
  922.  
  923.                    Copyright (C) InfoSoft, 1986-1990, 1991               14
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.              Name: DLight                   Type: FUNCTION
  931.          Syntax: errc = DLight(drive)
  932.  
  933.             DLIGHT triggers  the A: or B: drive light for the length of a 2
  934.      sector disk read.  This is helpful in demo or training programs to add
  935.      realism to the  session.  It uses  a BIOS level diskette  service call
  936.      and will return a FUNCTION error of -1 if you  attempt to invoke it on
  937.      a drive other  than 0 or  1 (A: and  B: respectively).   On the  other
  938.      hand, the drive light  will come on even if the drive  is open without
  939.      causing a "Drive Not Ready" error!    Example:
  940.          DECLARE FUNCTION DLight%(drive%)
  941.          .
  942.          .
  943.          IF DLight(drv) THEN
  944.             PRINT "Hey, dummy - I said A: or B: !")
  945.          END IF
  946.  
  947.  
  948.  
  949.              Name:  DlrFrmat                Type: FUNCTION   (BASIC)
  950.          Syntax: errc = DlrFrmat(numstr$, mode, point)
  951.  
  952.          This allows you  to format  a numeric string  to various  currency
  953.      conventions.  Your options include allowing a "$" in front or  not: if
  954.      you allow it, DLRFRMAT will check to see if  it is there and add it if
  955.      it  is not; if you  do not want  it, it will strip  it off if entered.
  956.      You also are allowed  to format it out to 2 or 3 decimals (tenths of a
  957.      cent).   Parameters:
  958.      nst$=String containing only numbers, "." or "$" to be formatted.
  959.  
  960.      Mode 0 - Returns numeric string without "$", forces a "." entry.
  961.  
  962.      Mode 1 - Returns numeric string with "$", forces "." entry.
  963.  
  964.      Point is used to tell DLRFRMAT how many decimals to pad to:
  965.               2 - pads "123." to "123.00"
  966.               3 - pads "45.1" to "45.100"
  967.               0 - automatic dollar decimal placement:
  968.                  "5" becomes ".05", "70" becomes ".70" and "146"           
  969.                   becomes "1.46"
  970.  
  971.          Example:
  972.          mode = 1 : DecPt=3
  973.          INPUT "Enter your wage: ",nst$              'user keys '7.50'
  974.          CALL dlrfrmat(nst$, mode, DecPt)
  975.          wag$ = nst$
  976.          PRINT nst$                                  'output: $7.500
  977.  
  978.          Note that in the case of an error, errc will be set accordingly:
  979.          -1 = Invalid Mode specified
  980.          -2 = Null string passed
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.                    Copyright (C) InfoSoft, 1986-1990, 1991               15
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.              Name: DosVer                   Type: FUNCTION
  997.          Syntax: OEM =  DosVer(Major, Minor)
  998.  
  999.          Returns the DOS Version the system is running under as well as the
  1000.      OEM  number, if  any) - this  is the  DOS supplier for  example, IBM's
  1001.      PC-DOS will return  00 as the OEM  number, DEC as 16h etc.   The Major
  1002.      and  minor versions will be correct regardless of the OEM.
  1003.  
  1004.  
  1005.  
  1006.              Name: DPRINT                   Type: SUB
  1007.          Syntax: CALL DPRINT(a$)
  1008.                  CALL DPrint("Hello, World")
  1009.  
  1010.          Beginning in QB4.00, the QB runtime library started to use a lower
  1011.      level method of  writing to  the screen for  normal PRINT  statements.
  1012.      This is good because it more or less builds in a QUICKPRINT feature to
  1013.      the language.   But it is bad if you  wish to occasionally use ANSI or
  1014.      other  features  that come  with DOS  level  prints.   DPRINT,  is the
  1015.      inverse of a QPRINT - it uses DOS to print to the screen so  that ANSI
  1016.      escape  codes are recognized  again.  Another  place that  this is ex-
  1017.      tremely helpful is when your application is running under a multitask-
  1018.      ing system  such as   DoubleDOS,  TaskView or  similar -  that is  the
  1019.      display output will not 'bleed' thru to the other side.  DPRINT should
  1020.      be declared so  that you can syntactically  use it the same  as PRINT.
  1021.      Example:
  1022.          DECLARE SUB DPRINT(a$)
  1023.          ..
  1024.          ..
  1025.          DPRINT CHR$(27) + "[2J"        ' <Esc>[2J is ASNI code to CLS
  1026.          DPRINT "Hello, world"
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.                    Copyright (C) InfoSoft, 1986-1990, 1991               16
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.              Name: DrvError                 Type: FUNCTION
  1064.          Syntax: errc = DrvError(drv$)
  1065.  
  1066.          DrvError is a very powerful and important function providing for a
  1067.      complete disk drive I/O Critical Error handler.  It is called with the
  1068.      string character of the  drive to test ("A",  "C" etc).  It returns  a
  1069.      code indicating the level  of readiness of that  drive for I/O  opera-
  1070.      tions to  allow you  to completely forego  ON ERROR  to trap  for open
  1071.      drive doors, unformatted disks etc.
  1072.  
  1073.          DrvError works  on several  levels: first  it takes  over the  DOS
  1074.      Critical Error Handler from BASIC -  to trap errors before BASIC  can.
  1075.      Next, it treats  drive B with special care, if you attempt DrvError on
  1076.      "B", it will poll the system BIOS to see how many floppies are actual-
  1077.      ly installed  to avoid "Insert  disk in Drive B:..."  messages.  Next,
  1078.      DrvError tries to force an error first by reading the requested drive,
  1079.      to test for drive door open, formatted disks etc.  Then it attempts to
  1080.      write to the drive  by creating a unique file name,  then deleting it.
  1081.      In any  test, if an  error occurs, our  Critical Error Handler  ISR in
  1082.      turn  calls DOS to  get the extended  error information,  tells DOS to
  1083.      abort  the  operation, then  uninstalls  the Critical  error  ISR, and
  1084.      returns the error code to you.
  1085.  
  1086.  
  1087.      Possible DrvError Returns:
  1088.              -1  = No Drive passed
  1089.              -2  = Attempt on non existent "B"
  1090.               0  = all is well - proceed with a light heart
  1091.          11, 26  = possible format errors
  1092.              15  = Bad drive (or path)
  1093.              19  = Write Protect error
  1094.              21  = Door Is open
  1095.              29  = misc Read error
  1096.              30  = Misc Write Error
  1097.              31  = Not formatted
  1098.              34  = Invalid change, (DNR)
  1099.              59  = Critical error
  1100.  
  1101.          See PhDrvSet and  PhDrvCLr for suggestions on handling the phantom
  1102.      drive flag.  DrvError requires DOS 3.0 or greater
  1103.          Example:
  1104.              INPUT "Drive to use: ", drv$
  1105.              errc = DrvError(drv$)
  1106.              IF errc THEN
  1107.                  PRINT "Error reading from drive ";drv$
  1108.                  GOSUB DrvFailure
  1109.              END IF
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.                    Copyright (C) InfoSoft, 1986-1990, 1991               17
  1122.  
  1123.  
  1124.  
  1125.  
  1126.  
  1127.  
  1128.              Name: DrvSpace                 Type: SUB
  1129.          Syntax: CALL DrvSpace(a, b, c, d)
  1130.  
  1131.          Returns Total clusters, bytes per  sector, available clusters, and
  1132.      sectors per cluster for the specified drive, allowing you to determine
  1133.      the overall drive space and/or free space.
  1134.          Parameters:
  1135.          Input:
  1136.          a - drive number to poll, 1= A:, 2=B: etc; 0 = default.
  1137.  
  1138.          Output:
  1139.          a - Returns sectors per cluster
  1140.          b - Returns available count of available clusters
  1141.          c - Returns bytes per sector
  1142.          d - Total clusters on drive
  1143.  
  1144.          Example:
  1145.          a=0                                    ' read default drive
  1146.          CALL drvspace(a, b, c, d)
  1147.          TotalSpace& = CLNG(a) * CLNG(c) * CLNG(d)
  1148.          FreeSpace& = CLNG(a) * CLNG(c) * CLNG(b)
  1149.  
  1150.  
  1151.  
  1152.              Name: EgaPrtScrn               Type: SUB
  1153.          Syntax: CALL EGAPrtScrn
  1154.  
  1155.          Instructs the BIOS  to ignore the default 25  line mode for Print-
  1156.      -Screen operations and check for the correct display size.  All future
  1157.      Print-Screens (either via keyboard or GLIB's PrtScrn) will respect the
  1158.      actual screen size.
  1159.  
  1160.                     
  1161.  
  1162.              Name: EqInfo                   Type: SUB
  1163.          Syntax: CALL EqInfo(Ram, Ser, Par, Game, Floppy)
  1164.  
  1165.          Returns some basic  hardware configuration information.   Extended
  1166.      CPU information is returned by CPUInfo, and additional Video subsystem
  1167.      is returned by VidInfo and VidType.
  1168.          Parameters
  1169.          RAM   - Returns the amount of DOS memory installed
  1170.          SER   - Returns number of serial ports installed
  1171.          PAR   - Returns number of parallel ports installed
  1172.          Game  - Returns 0/1 for game port installed
  1173.          Floppy- Returns 0,1,2 as number of physical floppies installed
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.                    Copyright (C) InfoSoft, 1986-1990, 1991               18
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194.              Name: ErrorMessage             Type: SUB
  1195.          Syntax: CALL ErrorMessage(msg$, row, attr, sfx)
  1196.          ErrorMessage can also be invoked with the shorter name 'ErrMsg'
  1197.  
  1198.          ErrorMessage is a complex and  useful subprogram designed to flash
  1199.      a defined  message  to the  screen,  pause 2  secs,  then restore  the
  1200.      screen.   It can be used for  more than just error messages, but since
  1201.      it restores the  screen after  the message display,  it seems  ideally
  1202.      suited  to error messages.   You determine  the line to  use, the sub-
  1203.      routine automatically centers the message.
  1204.  
  1205.          Parameters:
  1206.          msg$ = Message to display
  1207.          row = Line for message to display on
  1208.          attr = attribute to use
  1209.          sfx = Sound effects.  0=none 1=low tone
  1210.  
  1211.          Example:
  1212.          msg$="You must enter a customer name!"
  1213.          sfx=2
  1214.          CALL errmsg(msg$, 15, 31, sfx)
  1215.  
  1216.  
  1217.  
  1218.              Name: ExpandPath               Type: SUB
  1219.          Syntax: CALL ExpandPath(FilSpec$, FullName$)
  1220.  
  1221.          DOS  has  an undocumented  way of  expanding filenames  into fully
  1222.      qualified path  names, complete with  drive designation.   By  passing
  1223.      this routine a filename,  it is expanded into  a fully qualified  file
  1224.      spec.  Note that this DOES NOT do  a WHEREIS type function to find the
  1225.      correct drive path designation, but  merely appends the DEFAULT drive/
  1226.      path spec  to the  name.   This remains  very handy  for converting  a
  1227.      filespec  in the current directory  to a fully  qualified name so that
  1228.      you can change directories and then address that file by it's complete
  1229.      name.   The FullName$  where the  qualified name  is returned  MUST be
  1230.      initialized to 64 spaces.   The routine will pad the  return parameter
  1231.      with spaces to 'blank out' any previous return.
  1232.  
  1233.       Example:
  1234.          DatFil$ = "myfil.dat"
  1235.          fullname$ = SPACE$(64)
  1236.          CALL ExpandPath(DatFil$, FullName$)   ' expand
  1237.          DatFil$ = LTRIM$(RTRIM$(FullName$))   ' store in old variable
  1238.          CHDIR "\MAIN"                         ' move to main dir
  1239.  
  1240.          ' future references to DatFil$ will access the right file.
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.                    Copyright (C) InfoSoft, 1986-1990, 1991               19
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.              Name: ExtPut/ExtGet            Type: FUNCTION
  1261.          Syntax: errc = ExtPut(SEG DBlock, EPage, Bytes)
  1262.                  errc = ExtGet(SEG DBlock, EPage, Bytes)
  1263.  
  1264.            ExtPut  and Extget  allow  your application  to  access and  use
  1265.      EXTENDED memory.  This is NOT LIM/EMS memory but the memory found only
  1266.      on  286  or 386  systems and  usually  associated with  protected mode
  1267.      operations.  Such systems with more than 640k (usually 1MB) of onboard
  1268.      memory will have EXTENDED memory and usually use it either as  a print
  1269.      spooler, ram disk or disk cache.
  1270.  
  1271.          ExtPut and ExtGet allow you to actually store and retrieve data to
  1272.      and  from  EXTENDED memory,  which may  add  as much  as 384k  of such
  1273.      'parking' memory to your larger programs.   Note that the program does
  1274.      not  execute in EXTENDED memory,  but will be able  to use it for data
  1275.      storage (usually an array).   Once data from an array  is moved there,
  1276.      it can  be  erased or  REDIMmed  to hold  something  else, then  later
  1277.      resized and the  data fetched  back into DOS  conventional memory  for
  1278.      your program to access  once again.  That is, data  stored or 'parked'
  1279.      in EXTENDED memory cannot be directly accessed by your program, but it
  1280.      can be fetched back for access.
  1281.  
  1282.      For purposes  of these  routines, we  have broken  the 384k  (usually)
  1283.      block of  memory into 24 blocks of  16k of storage which  will term as
  1284.      PAGES.  These pages  or blocks are  referenced as 0 thru  24.  So,  to
  1285.      store data at the 1MB mark, EPage should be set to 0, to store data in
  1286.      the second 16k block past the 1MB  point, set EPage to 2 and so forth.
  1287.      You  may move more than 16k at a time, indeed up to 64k of data may be
  1288.      moved in one  call, but the 16k  page size allows for  maximum utiliz-
  1289.      ation of extended memory with a minimum of waste.
  1290.  
  1291.  
  1292.      ExtPut moves  BYTES number of bytes from  the passed array (DBLOCK) TO
  1293.      extended memory into  the 'parking' spot EMark  * 16k above the  1 meg
  1294.      mark.  ExtGet,  on the other hand  fetches BYTES number of  bytes from
  1295.      the specified parking  spot INTO DOS conventional  memory specified by
  1296.      DBLOCK.   Even if you are not moving  to or from an array, DBLOCK must
  1297.      be passed as a SEG parameter.  To pass more than 32k as the  number of
  1298.      bytes to move, use negative numbers for the BYTES parameter.
  1299.  
  1300.          ExtPut and  ExtGet are functions  that return the  following error
  1301.      codes:
  1302.          0 = Move went ok
  1303.          1 = EXTENDED memory RAM parity error
  1304.          2 = interrupt error
  1305.          3 = gate address failed
  1306.  
  1307.  
  1308.          A few notes on using Extended memory:
  1309.          1) This should be considered a very advanced routine and          
  1310.             should NOT be utilized  by you if you do not understand what   
  1311.             EXTENDED and EXPANDED memory are and how they differ.
  1312.          2) Again, this is NOT EMS/EXPANDED memory.
  1313.  
  1314.  
  1315.  
  1316.  
  1317.  
  1318.  
  1319.                    Copyright (C) InfoSoft, 1986-1990, 1991               20
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.          3) Moving less than 16k to or from EXTENDED memory  still         
  1327.             utilizes the entire 16k page.  That is, 8k cannot be           
  1328.             stored in the lower half of a block with the hopes  of         
  1329.             storing another 5 to  8k in the upper half of that block.      
  1330.             This is designed this way to minimize extended memory          
  1331.             wastage and aid in managing what data is where: there
  1332.             are generally only 24 blocks to keep track of.   Note that     
  1333.             is it up  to your program to manage the data and what is       
  1334.             stored where.
  1335.          4) Unless you are  using this in your application on your         
  1336.             machine, you have no assurances that EXTENDED memory is        
  1337.             not already in use as  a spooler, ram disk or cache.  To       
  1338.             check this, simply perform a few ExtGets of 16k on the         
  1339.             first few pages and if the entire array is NOT 0,              
  1340.             something else is using it and you should NOT store any        
  1341.             data anywhere in EXTENDED memory.  Uninitialized  EXTENDED     
  1342.             memory should always be ZEROES.  If ANYTHING is using ANY      
  1343.             EXTENDED memory, you have no assurances that it might not      
  1344.             allocate more later and overwrite your data - or  worse,       
  1345.             you could trash a VDisk with valuable data or  wreck the       
  1346.             hard disk FAT by  trashing an EXTENDED memory cache.  To       
  1347.             determine whether a ExtGet is reading a cache, spooler or      
  1348.             VDisk or possibly reading old data stored there by a dif-      
  1349.             ferent application of yours,  force a COLD BOOT at the end     
  1350.             of your application to  clear all memory or store an ID        
  1351.             byte sequence at the start or end of the first block.
  1352.          5) Use of this routine means that your program will NOT run       
  1353.             under OS/2 in the DOS compatibility box.
  1354.          6) Some 8088 PC's, low quality clones in particular, may          
  1355.             crash and burn on  this routine.  So rather than depending     
  1356.             on the return from either Extget or ExtPut to  determine       
  1357.             if it will work, use the GLIB functions CPUInfo and/or         
  1358.             ExtMem to determine system type.
  1359.          7) Use of these  functions requires that the CPU be placed        
  1360.             into protected mode, and may cause a loss  of some             
  1361.             interrupts.   For example, one or more characters MAY be       
  1362.             lost in programs that  use ongoing serial communications       
  1363.             when either ExtPut or ExtGet are executed.
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.                    Copyright (C) InfoSoft, 1986-1990, 1991               21
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391.  
  1392.              Name: ExtMemFree               Type: FUNCTION
  1393.          Syntax: AtMem = ExtMemFree
  1394.  
  1395.          Returns the amount of extended, or AT memory, that is installed in
  1396.      a 286 based machine, but NOT  allocated or in use.  Many  applications
  1397.      that use extended memory now capture  this interrupt and either return
  1398.      0k of extended memory  or that amount that is unallocated.  Use of the
  1399.      ExtPut and ExtGet DO  NOT alter the number  returned by this  routine.
  1400.      This only works on AT's or AT clones (80286 based machines).
  1401.          mem = ExtMem
  1402.          PRINT "AT/286 has ";mem;" of extended memory free."
  1403.  
  1404.  
  1405.  
  1406.              Name: ExtMemInst               Type: FUNCTION
  1407.          Syntax: AtMem = ExtMemInst
  1408.  
  1409.          Returns the amount of extended, or AT memory, that is installed in
  1410.      a  286 based machine.  This routine  bypasses the interrupt that typi-
  1411.      cally is captured to return a  modified or zero extended memory value.
  1412.      This returns the actual amount of  extended memory installed and known
  1413.      to the  system.   This  only works on  AT's or AT clones  (80286 based
  1414.      machines).
  1415.          mem = ExtMemInst
  1416.          PRINT "AT/286 has ";mem;" of extended memory installed."
  1417.  
  1418.  
  1419.  
  1420.             Name: FADE                      Type: SUB
  1421.          Syntax: CALL Fade
  1422.  
  1423.          This is an interesting alternative  to CLS.  It quickly reads  the
  1424.      character at  each location  on the  screen and  decrements the  ASCII
  1425.      value  of it  until  it reaches  32  (space).   The  attribute (color)
  1426.      remains  the same during and after the FADE.  Because of the nature of
  1427.      this effect,  it must be done quickly and  without the overhead of the
  1428.      video retrace for CGAs.  As a result this routine WILL cause snow on a
  1429.      CGA and should only be used on MONO, EGA or VGA systems.
  1430.  
  1431.  
  1432.  
  1433.  
  1434.              Name: FAttrGet                 Type: FUNCTION
  1435.          Syntax: errc = FAttrGet(fil$, fattr)
  1436.  
  1437.            Access to get  the file attributes for a given file.  Subsequent
  1438.      calls to SetFattr (qv) allow you to set or reset a file attribute.
  1439.          File attributes are as follows:
  1440.              00  -  Normal             04  -  System
  1441.              01  -  Read Only          32  -  Archive
  1442.              02  -  Hidden
  1443.  
  1444.            The archive bit is usually used by back up programs to determine
  1445.      if a file has been backed up since the last write process.  To combine
  1446.      attributes, just add  the values, ie:  Read Only -  Hidden would be  3
  1447.      because 1+2=3.
  1448.  
  1449.  
  1450.  
  1451.                    Copyright (C) InfoSoft, 1986-1990, 1991               22
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458.             This is a function and therefore also returns any error code in
  1459.      the name of  the function that can  be evaluated itself,  or assigned.
  1460.      An error  will result if  the filename passed  is not found (6).   See
  1461.      also FAttrSet.    Error Codes:
  1462.          -1 = Invalid File attribute
  1463.           2 = File not found
  1464.           3 = Path not found
  1465.           5 = Access denied
  1466.  
  1467.          Example:
  1468.          DECLARE FUNCTION FAttrGet%(fil$, attrib%)
  1469.          .
  1470.          .
  1471.          fil$ = "myfil.txt"
  1472.          failure = FAttrGet(fil$, attrib)
  1473.          IF failure THEN PRINT "Sorry, cannot find ";fil$
  1474.  
  1475.  
  1476.  
  1477.  
  1478.              Name: FAttrSet                 Type: FUNCTION
  1479.          Syntax: errc = FAttrSet(fil$, fattr)
  1480.  
  1481.            FAttrSet allows you to change or  modify the file attributes for
  1482.      any disk file that exists.  For a table of the attributes, see
  1483.      FAttrGet.  FattrSet  is a function returning an error code.  (DOS will
  1484.      not allow changes to volume labels  or directories via this function.)
  1485.      Example:
  1486.          DECLARE FUNCTION FAttrSet%(fil$, attrib%)
  1487.          .
  1488.          .
  1489.          fil$="myprog.sys" 
  1490.          attrib=3                        ' make it Read Only, Hidden
  1491.          IF FAttrSet(fil$, attrib) THEN
  1492.              PRINT "Error - possible invalid file attribute."
  1493.          ELSE
  1494.              PRINT "Change succeeded."
  1495.          END IF
  1496.  
  1497.  
  1498.  
  1499.                    
  1500.             Name: FClose                    Type: FUNCTION
  1501.          Syntax: errc = FClose(handle)
  1502.  
  1503.            As expected, FCLOSE performs the opposite  of FOPEN, close out a
  1504.      file handle opened via FOPEN.   FCLOSE does some positive error check-
  1505.      ing to make sure that you do  not attempt to close one of the standard
  1506.      DOS file  handles (like the  keyboard, monitor etc) and  will return a
  1507.      error code of 6 - Invalid File handle.
  1508.  
  1509.          See also  FOpen FUnique, FCreat, FSetPtr, and  DOS File Functions.
  1510.          Example:
  1511.          DECLARE FUNCTION FClose%(fhandle%)
  1512.          .
  1513.          .
  1514.          result = fclose(fhandle)
  1515.          IF result THEN GOSUB ErrorControl
  1516.  
  1517.                    Copyright (C) InfoSoft, 1986-1990, 1991               23
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525.  
  1526.  
  1527.              Name: FCopy                    Type: FUNCTION
  1528.          Syntax: errc = FCopy(source$, dest$, buffer$)
  1529.  
  1530.          This function  copies a disk file  using a buffer  supplied by the
  1531.      main program, to perform about as  fast as the DOS COPY command.   You
  1532.      also pass it a source and destination string (paths / drives  are ok).
  1533.      The FUNCTION returns a variety of error conditions:
  1534.          -1 = Null string passed as source or destination
  1535.           2 = File Not Found
  1536.           3 = Path not Found
  1537.           4 = No Handle ("Too Many Files")
  1538.           5 = Access Denied
  1539.  
  1540.      Example:
  1541.        DECLARE FUNCTION FCopy%(source$, dest$, buffer$)
  1542.         .
  1543.         .
  1544.        result = fcopy("GLIB.ARC","\GOODSTUFF\GLIB.ARC", SPACE$(4096))
  1545.  
  1546.        IF result THEN PRINT "Oops!  Error - Check parameters!"
  1547.  
  1548.      * Note the  use of SPACE$  to supply the  buffer.  This  automatically
  1549.      creates a temporary  buffer - upon the  return from FCOPY, the  buffer
  1550.      memory is released.
  1551.  
  1552.  
  1553.            
  1554.              Name: FCount                   Type: FUNCTION
  1555.          Syntax: NumFiles = FCount(fil$)
  1556.          FCount may also be invoked as FilCnt.
  1557.  
  1558.          This is can  be an indispensable tool - it quickly returns a count
  1559.      of  the number of  files matching the  given mask.   This is extremely
  1560.      useful in determining  how large  an array  should prior to  a Dir  or
  1561.      DirFLS call.  If an invalid path or drive is included in the mask$, no
  1562.      files will be found.
  1563.  
  1564.  
  1565.  
  1566.              Name: FCreat                   Type: FUNCTION
  1567.          Syntax: errc = FCreat(fil$, attrib, handle)
  1568.  
  1569.            FCREAT is similar  to FOPEN  except that instead  of opening  an
  1570.      existing file, we are CREATING a NEW file.  As with FOPEN, and all the
  1571.      DOS File Functions, error codes returned  in the BASIC FUNCTION format
  1572.      and are:
  1573.          -1    Null string passed
  1574.           3    Path not found
  1575.           4    No handle available ("Too many files")
  1576.           5    Access denied (this is returned when attempting  to         
  1577.      FCreat a file that already exists - use FOpen in this           case).
  1578.  
  1579.          Note: You are  encouraged to use FEXIST  first to see if  the file
  1580.      already exists, executing FCREAT on an existing file truncates it to 0
  1581.      bytes.
  1582.  
  1583.                    Copyright (C) InfoSoft, 1986-1990, 1991               24
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590.  
  1591.          Example:
  1592.          DECLARE FUNCTION FCreat%(fil$, attrib%, fhandle%)
  1593.          .
  1594.          .
  1595.          fil$="mainprg.sys": attrib=0
  1596.          IF fcreat(fil$, attrib, fhandle)=0 THEN
  1597.              PRINT "New file, ";fil$;" successfully created!"
  1598.          ELSE
  1599.              GOSUB WhatsGoingOn
  1600.          END IF
  1601.  
  1602.  
  1603.  
  1604.  
  1605.              Name: FDateGet/FDateSet        Type: FUNCTION
  1606.          Syntax: errc = FDateGet(handle%, mo%, day%, yr%)
  1607.                  errc = FDateSet(handle%, mo%, day%, yr%)
  1608.  
  1609.          These allow you  to SET or GET  the date for a file  for which you
  1610.      have an open handle.  (Use FOpen or BASIC's FILEATTR to get a handle).
  1611.      You may set the  file date for a handle, then continue  to perform I/O
  1612.      on that  file and be  assured that once closed,  the file will  be set
  1613.      with the desired date.  The only likely return code would  be that the
  1614.      handle% parameter is not  a valid DOS handle.  The  year parameter may
  1615.      be either 2 or 4 digits (ie 1989 or 89).  Eg:
  1616.          OPEN "foo.bar" FOR RANDOM AS #1
  1617.          handle = FILEATTR(1,2)
  1618.          errc = FDateSet(handle, 1, 1, 80)   ' set date to 1/1/1980
  1619.  
  1620.  
  1621.                   
  1622.              Name: FDelete                  Type: FUNCTION
  1623.          Syntax: errc = FDelete(fil$)
  1624.  
  1625.          Simply deletes the file indicated by fil$ from the disk.  The file
  1626.      should NOT  be open.   This  uses the  DOS function  UNLINK to  simply
  1627.      remove the first character so it may be UNDeleted with any of a number
  1628.      of Disk tools.   Example:
  1629.          errc = FDelete("foo.bar")
  1630.  
  1631.  
  1632.              Name: FDiskType                Type: FUNCTION
  1633.          Syntax: NumHDs = FDiskType(DrvNo, Cyl, Sectors, Heads)
  1634.  
  1635.          Returns information regarding the installed fixed disk.  On entry,
  1636.      set DrvNo to  the drive to poll (0 = first  hard disk etc).  The func-
  1637.      tion  returns  the total  number  of  fixed disks  installed,  and the
  1638.      Cylinder, Sector and Head count of the drive requested.  Example:
  1639.          NumDrvs = FDiskType(0, Cyls, Secs, Hds)
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648.  
  1649.                    Copyright (C) InfoSoft, 1986-1990, 1991               25
  1650.  
  1651.  
  1652.  
  1653.  
  1654.  
  1655.  
  1656.              Name: FEOF                     Type: FUNCTION
  1657.          Syntax: errc = FEOF(fhandle)
  1658.  
  1659.             Sets the file  pointer to the end  of a file opened  via FOPEN.
  1660.      This actually sets  the pointer to ONE  BYTE less than the  end of the
  1661.      file.  This is  to be sure  that subsequent FWRITE funtions  overwrite
  1662.      any hard EOF markers  (ASCII 26) left by many text  editors. FEOF also
  1663.      checks for invalid handles as well  as the 4 standard DOS handles  and
  1664.      aborts to return an error code of 6 - Invalid handle.  Using FOPEN and
  1665.      then FEOF is  the equivalent of  opening a file  in APPEND mode  using
  1666.      BASIC's intrinsic file functions.  See also: FSetPtr.  Example:
  1667.          DECLARE FUNCTION FEOF%(fhandle%)
  1668.          .
  1669.          IF FOpen("longtext.fil", 0, fhandle) THEN
  1670.              GOSUB StartNewFile
  1671.          ELSE
  1672.              j= feof(fhandle)
  1673.              IF j THEN GOSUB WeirdError
  1674.              GOTO AppendToText
  1675.          END IF
  1676.  
  1677.              Name: FExists                  Type: FUNCTION
  1678.          Syntax: ExistCode = FExists(fil$)
  1679.          This may also be called as FileExists
  1680.  
  1681.             Sets the return code (non zero) if the given file exists and no
  1682.      path or other error is encountered.  See also FileDNE. 
  1683.      Example:
  1684.  
  1685.          DECLARE FUNCTION FExists%(fil$)
  1686.          ..
  1687.          fil$ = "foo.bar"
  1688.          IF FExists(fil$) THEN
  1689.              PRINT fil$;" already exists! Overwrite?"
  1690.          END IF
  1691.  
  1692.  
  1693.  
  1694.             Name: FFlush                    Type: FUNCTION
  1695.          Syntax: errc= FFlush(Fhandle)
  1696.  
  1697.          FFlush  will  dump any  buffered  data  to disk  much  faster than
  1698.      closing and then  reopening the file will.   FFlush will NOT  dump the
  1699.      buffer for files opened using QB functions - QB does  some significant
  1700.      buffering of its own that does not respond to FFlush.  Pass FFlush the
  1701.      handle associated with  the file, any  return indicates an error  code
  1702.      the same as the other DOS file functions.  Example:
  1703.          errc = FFlush(fhandle)
  1704.  
  1705.  
  1706.  
  1707.              Name: FFlushAll         Type: SUB
  1708.          Syntax: CALL FFlushA
  1709.  
  1710.          Flushes all DOS file buffers to disk and updates disk directories.
  1711.      This will not update the directories of files that are currently open.
  1712.      This is  in contrast to  FFlush that both commits  a file to  disk and
  1713.      updates the disk directory for a specific open file handle.
  1714.  
  1715.                    Copyright (C) InfoSoft, 1986-1990, 1991               26
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.              Name: FHFree                 Type: FUNCTION
  1724.          Syntax: FreeH = FHFree%
  1725.  
  1726.          Returns an integer representing the number of file handles free or
  1727.      unallocated or available.  See also FHMax, FHUsed.
  1728.  
  1729.  
  1730.              Name: FHMax             Type: FUNCTION
  1731.          Syntax: MaxH = FHMax%
  1732.  
  1733.          Returns  the  number of  maximum  file  handles  available to  the
  1734.      system.  DOS  by default allows  20 handles, but more  or less can  be
  1735.      available by using the FILES command in CONFIG.SYS.  FHMax returns the
  1736.      number configured by CONFIG.SYS.  See also FHFree and FHUsed.
  1737.  
  1738.  
  1739.              Name: FHUsed                 Type: FUNCTION
  1740.          Syntax: HUsed = FHUsed
  1741.  
  1742.          Returns the  number of file handles in use  by the system or other
  1743.      processes.  By default, DOS will use several handles for  the standard
  1744.      devices (stdaux, stdprn, stderr, stdout and  stdin), and others may be
  1745.      in use by TSR's, or other processes.  Note that FHMax less FHUsed will
  1746.      equal FHFree.  See also FHFree, FHMax.
  1747.  
  1748.  
  1749.  
  1750.              Name: FileDNE                  Type: FUNCTION
  1751.          Syntax: errc = FileDNE(fil$)
  1752.          This may also be called as FNotFound
  1753.  
  1754.          This provides the inverse to the logic found in FExists.   Instead
  1755.      of testing if a file DOES exist,  it returns non zero if the file DOES
  1756.      NOT exist.  This can be handy for logic or statements that work better
  1757.      with the non zero return.  See also FExists. Example:
  1758.  
  1759.          'REM Instead of:  
  1760.        IF NOT FExists(Fil$)   or   IF FExists(fil$) = 0
  1761.        IF FileDNE(fil$) THEN
  1762.            PRINT "File Does Not Exist."
  1763.        END IF
  1764.  
  1765.  
  1766.  
  1767.              Name: FInfo             Type: FUNCTION
  1768.          Syntax: errc = FInfo(FilMask$, SEG FileInfo AS structf)
  1769.  
  1770.          Returns compleat information about the file specified by FilMask$.
  1771.      The information is  returned in a  user defined data structure  (TYPE)
  1772.      that is as follows (feel free to change names, but NOT the order!):
  1773.  
  1774.  
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780.  
  1781.                    Copyright (C) InfoSoft, 1986-1990, 1991               27
  1782.  
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.          TYPE structf
  1789.             FilAttr AS INTEGER          ; the file attribute
  1790.             FilHour AS INTEGER          ; the file time Hour
  1791.             FilMin  AS INTEGER          ; the file time Minute
  1792.             FilSec  AS INTEGER          ; the file time Seconds
  1793.             FilMon  AS INTEGER          ; the file date Month
  1794.             FilDay  AS INTEGER          ; the file date Day
  1795.             FilYr   AS INTEGER          ; the file date Year
  1796.             FilSiz AS LONG              ; the size (in bytes) of the file
  1797.             FilSpec AS STRING * 12      ; the file name (no wildcards)
  1798.          END TYPE
  1799.  
  1800.         DIM FilInfo AS Structf
  1801.         errc = FInfo("*.exe", FilInfo)
  1802.         PRINT USING "Name: &  Size: ########";FilInfo.FilSpec;_
  1803.                        FilInfo.FilSiz
  1804.  
  1805.          errc returns any error condition found by FInfo:
  1806.          -1 = File not found (check the path)
  1807.          -3 = Mask error (FMask$ may be "")
  1808.  
  1809.          The  biggest  use for  this  function  is to  fetch  more compleat
  1810.      information on a known file.   While using wildcards are OK, only  the
  1811.      first file matching the mask is returned, ie there is no FindNextFInfo
  1812.      routine.  Once  your program is sure  of the location (path)  and name
  1813.      use FInfo to fetch the rest of the name or use FInfoA (see also).
  1814.  
  1815.  
  1816.  
  1817.              Name: FInfoA                 Type: FUNCTION
  1818.          Syntax: errc = FInfoA(FilMask$, SEG FileInfo() AS structf)
  1819.  
  1820.          This works identically  to Finfo except  that it fetches the  file
  1821.      information into a user defined data structure ARRAY.  Useful when you
  1822.      need complete information on all .EXE  files, or all .DAT files.   The
  1823.      TYPE structure  is identical to that  in FInfo (see also).   Wildcards
  1824.      are advisable and BE SURE to dimension  the array large enough to hold
  1825.      all the files that will may found:
  1826.  
  1827.          fmask$ = "*.dat"                    ' fetch data files
  1828.          QFiles = FCount(fmask$)             ' (qv) count number of files
  1829.  
  1830.          REDIM FilInfo(QFiles) AS Structf    ' large enough and right type
  1831.  
  1832.          errc = FinfoA(FMask$, FilInfo(1))
  1833.  
  1834.          FOR x = 1 TO QFiles
  1835.              ' print name and size
  1836.              PRINT FilInfo(x).FilSpec; FilInfo(x).FilSiz
  1837.          NEXT x
  1838.  
  1839.  
  1840.              Name: FlexMenu                 Type: FUNCTION
  1841.          Syntax:  item = MenuChoice%  (Menu$(), Trow%, LCol%, Nattr%,_     
  1842.                  Hattr%, Title$, Mark%(), XtdChc%)
  1843.  
  1844.          Extensive Menuing function fully documented in MACROxx.DOC.
  1845.  
  1846.  
  1847.                    Copyright (C) InfoSoft, 1986-1990, 1991               28
  1848.  
  1849.  
  1850.  
  1851.  
  1852.  
  1853.  
  1854.  
  1855.  
  1856.              Name: FindFirst                Type: FUNCTION
  1857.          Syntax: errc = FindFirst(mask$, ret$)
  1858.          FindFirst may also be called as FileFirst
  1859.  
  1860.          This provides a simple,  easy and straight forward access  to disk
  1861.      directories by seeking the first file matching the given mask.  Things
  1862.      such as an invalid  path or drive will force an error return.  If errc
  1863.      is clear (zero), then ret$ will hold the name of the first file found.
  1864.      Since FirstF is in assembler, you must initialize ret$ to 12 spaces to
  1865.      hold  the returned name (Fewer than 12 spaces, and FirstF will provide
  1866.      as many characters as possible,  and set the Error Flag -  but no way,
  1867.      no how  will your  error result  in String  Space Corrupt  errors with
  1868.      GLIB!).  Use FindNext to get subsequent matching files.  FindFirst can
  1869.      be used as a form  of finding out if a file exists and  even if a path
  1870.      is valid or not.   Example:
  1871.          DECLARE FUNCTION FindFirst%(mask$, retf$)
  1872.          ..
  1873.          retf$ = SPACE$(12)
  1874.          mask$ = "\BIN\UTILITIES\*.COM"   ' try for list of COM files
  1875.                                           ' in \BIN\UTILITIES dir
  1876.  
  1877.          errc = FindFirst(mask$, ret$)
  1878.          IF errc THEN
  1879.              .. something is wrong: path, none found etc
  1880.          ELSE
  1881.             ... retf$ holds filename of first \BIN\UTILITES\COM 'files
  1882.          END IF
  1883.  
  1884.  
  1885.  
  1886.  
  1887.              Name: FindNext                 Type: FUNCTION
  1888.          Syntax: errc = FindNext(ret$)
  1889.          FindNext may also be called as FileNext
  1890.  
  1891.          This  returns  subsequent filenames  matching  the mask  passed in
  1892.      FindFirst.   The  mask need  not  be passed  again, but  ret$  must be
  1893.      initialized to  12 or  more spaces.   Once a  successful FindFirst  is
  1894.      executed, the only  likely error return in errc is 18 that signals "no
  1895.      files found".  Example:  (more code intensive than DirA or DIRFLS)
  1896.          DECLARE FUNCTION FindFirst%(mask$, retf$)
  1897.          DECLARE FUNCTION FindNext%(ret$)
  1898.          ..
  1899.          retf$ = SPACE$(12)
  1900.          mask$ = "\BIN\UTILITIES\*.COM"      ' look thru COM files
  1901.                                              ' in \BIN\UTILITIES dir
  1902.          errc = FindFirst(mask$, ret$)
  1903.          IF errc THEN
  1904.              .. something is wrong: path, none found etc
  1905.          ELSE
  1906.              DO
  1907.                  ret$ = SPACE$(12)
  1908.                  errc = FindNext(ret$)
  1909.              LOOP UNTIL (errc=18) or ( INSTR(ret$, "FOOBAR.COM") )
  1910.             ' loop until no more file found, or a specific file is found
  1911.          END IF
  1912.  
  1913.                    Copyright (C) InfoSoft, 1986-1990, 1991               29
  1914.  
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921.              Name: FlexType                 Type: FUNCTION
  1922.          Syntax: FlexCode = FlexType(drv, NumFlex)
  1923.  
  1924.          Returns the number of installed  flex disk drives ("floppies") and
  1925.      a type code for the specified drive.  NumFlex returns with the actual,
  1926.      physical number  of flex  drives  installed, FlexCode  returns a  code
  1927.      identifying the type of flex DRIVE (NOT flex DISK!) installed:
  1928.           -1 = Invalid drive requested
  1929.           00 = Unknown drive type or function not supported (See note)
  1930.           01 = 360k 5.25"
  1931.           02 = 1.2MB 5.25"
  1932.           03 = 720k 3.5"
  1933.           04 = 1.4MB 3.5"
  1934.           Note: Older 8088  PC BIOSes,  do not support  this function,  and
  1935.      return -1 noting this; cheaper clones may even lock up, so invoke this
  1936.      on 8088 systems at your own risk (A PC most likely has a 360k drive).
  1937.  
  1938.  
  1939.  
  1940.              Name: FMove                    Type: FUNCTION
  1941.          Syntax: errc = FMove(source$, dest$, buffer$)
  1942.  
  1943.          This  works the same  as a  FCopy/FDelete combination  with source
  1944.      file being  deleted after the  destination file  is created.   As with
  1945.      FCopy and FPrint,  you supply the buffer by simply passing a string or
  1946.      temporary  variable.  Any errc return  indicates an error such as disk
  1947.      full, file already exists and is Read  Only, or disk is write protect-
  1948.      ed.  The source and destination file name may be on different devices.
  1949.      Example:
  1950.          errc = FMove("foo.bar", "A:foo.bak", SPACE$(4096))
  1951.  
  1952.  
  1953.  
  1954.              Name: FOpen                    Type: FUNCTION
  1955.          Syntax: errc = FOpen(fil$, mode, fhandle)
  1956.  
  1957.            FOPEN is  a standard  DOS function  to open  a file  via a  file
  1958.      handle.   FOPEN  requires a  'mode'  be passed,  1  = multitasking  or
  1959.      networking, 0 = normal.   There is a way  to set access rights  (read,
  1960.      write,  read/write)  that also  may be  implemented  later.   DOS even
  1961.      reserves a special handle for your printer (see: "Dos File Functions")
  1962.      In order to keep the number of parameters  down, the fhandle parameter
  1963.      is  used to  pass back  the file  handle and  FOPEN is  designed as  a
  1964.      FUNCTION in assembler to return any error codes the same as a FUNCTION
  1965.      operates in BASIC.
  1966.      An error can occur if the file handle is  invalid, the file is already
  1967.      open,  file not found etc.  In this case, the errorcode or result will
  1968.      indicate what happened and any fhandle number should be ignored.
  1969.          Example:
  1970.          DECLARE FUNCTION FOpen%(fil$, mode%, fhandle%)
  1971.          ..
  1972.          fil$="myprog.dat" : mode=0
  1973.          IF fopen(fil$, mode, fhandle) THEN
  1974.              GOSUB FileError
  1975.          ELSE
  1976.              PRINT fil$;" opened with a handle of ";fhandle
  1977.          END IF
  1978.  
  1979.                    Copyright (C) InfoSoft, 1986-1990, 1991               30
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.             
  1987.              Name: FPrint                      Type: SUB
  1988.          Syntax: CALL FPrint(doc$, buffer$)
  1989.  
  1990.             Send a  file from disk  to the first  printer (LPT1,  PRN etc).
  1991.      This is a much handier way to print a file rather than reading it line
  1992.      by line and LPRINTing it, and takes  as much memory as you lend it  by
  1993.      way of the buffer.  Regardless, it takes less  memory than to SHELL to
  1994.      DOS  and copy it to the printer and  is faster than to LINE INPUT each
  1995.      line and LPRINT it.    This routine  will not abort if the  printer is
  1996.      not ready, test for printer readiness with PtrStat. Example:
  1997.          printfil$="GLIB16.DOC"
  1998.          CALL FPrint(printfil$, SPACE$(4096))
  1999.  
  2000.  
  2001.  
  2002.  
  2003.              Name: FReadArray               Type: FUNCTION
  2004.          Syntax: errc = FReadArray(SEG arry, Fhandle, BYTES)
  2005.  
  2006.          FReadArray reads data  from a  disk file directly  into an  array.
  2007.      The file  must have  a  valid DOS  File Handle  which is  accomplished
  2008.      either by using  FOpen or FILEATTR on  a BASIC file number.   Elements
  2009.      indicates the number  of BYTES to fill (remember that each elements in
  2010.      the array is 2 Bytes), upon return from the function BYTES is reset to
  2011.      the actual number  read (in  case EOF  is encountered  before all  the
  2012.      requested bytes can  be read).  ERRC is set to  indicate any DOS error
  2013.      encountered.    See  the complimentary  function FWriteArry;  GLIBDEMO
  2014.      shows a practical use - binary screen libraries.
  2015.          Example:
  2016.  
  2017.          DECLARE FUNCTION FReadArry%(SEG arry%, Fhandle%, Bytes%)
  2018.          ..
  2019.          ..
  2020.          REDIM ScrnArry(2000)             ' 2000 elements = 1 screen
  2021.          fil = FREEFILE                   ' get next BAS file no
  2022.          OPEN "screens" FOR OUTPUT AS #fil
  2023.          handle = FILEATTR(fil,2)
  2024.          Bytes = 4000                     ' 2000 * 2
  2025.          errc = FreadArray(ScrnArry(1), handle, Bytes)
  2026.  
  2027.  
  2028.  
  2029.              Name:FReadByte/FWriteByte      Type: FUNCTION
  2030.          Syntax: errc = FReadByte(handle, byte)
  2031.                  errc = FWriteByte(handle, byte)
  2032.  
  2033.          This is similar to BASIC native BINARY file I/O, allow single byte
  2034.      file access.   This is not a character  but a byte, or the ASCII value
  2035.      of the byte ( ASC(ch$) ) to be sent or read from disk.
  2036.          You must have a valid, open handle for the destination file  - use
  2037.      FOpen or BASIC's FILEATTR  for this.  This can be considerably quicker
  2038.      for byte I/O  than BASIC's BINARY method of allocating  a string, then
  2039.      GETting and so forth.   Example  Read 5 bytes:
  2040.          FOR x = 1 TO 5
  2041.              errc = FReadByte(handle, byte)
  2042.              PRINT "Byte #";x;" is: "; byte
  2043.          NEXT x
  2044.  
  2045.                    Copyright (C) InfoSoft, 1986-1990, 1991               31
  2046.  
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.              Name: FReadStr                 Type: FUNCTION
  2054.          Syntax: errc = FReadStr(Thing$, Fhandle, chars)
  2055.  
  2056.          FReadStr  reads  data from  a  disk  file directly  into  a string
  2057.      variable.   The file  must have a  valid DOS File  Handle which is ac-
  2058.      complished either by using FOpen  or FILEATTR on a BASIC  file number.
  2059.      Elements indicates the  number of  CHARACTERS or BYTES  to read,  upon
  2060.      return from the function, CHARS is reset to the actual number read (in
  2061.      case EOF is  encountered before  all the requested  characters can  be
  2062.      read).  ERRC  is set to indicate  any DOS error encountered.   Because
  2063.      FReadStr is in high-speed assembler, you must initialize the buffer or
  2064.      string that will hold the read data  to at least as long as the number
  2065.      of characters to read or an  error will occur.  See the  complimentary
  2066.      function FReadStr.
  2067.  
  2068.      Example:
  2069.          DECLARE FUNCTION FReadStr%(Buffer$, Fhandle%, Bytes%)
  2070.          ..
  2071.          ..
  2072.          message$ = SPACE$(25)
  2073.          chars = 25
  2074.          fil = FREEFILE                      ' get next BAS file no
  2075.          OPEN "screens" FOR OUTPUT AS #fil
  2076.          handle = FILEATTR(fil,2)
  2077.          errc = FReadStr(Message$, handle, chars)
  2078.  
  2079.  
  2080.  
  2081.  
  2082.              Name: FRecGet/FRecPut          Type: FUNCTION
  2083.          Syntax: errc = FRecGet(handle, size, SEG struct)
  2084.                  errc = FRecPut(handle, size, SEG struct)
  2085.  
  2086.          These perform essentially  the same function as QB's GET # and PUT
  2087.      #  by reading a  single record from  the current location  of the file
  2088.      pointer represented by the handle passed.  Use FsetPtr (qv) to set the
  2089.      file pointer  to the desired  location.  These  are the  single record
  2090.      version of FRecGetA/FRecPutA (qv).   In using these over  PUT/GET, you
  2091.      can completely  bypass QB's  file I/O,  buffering and obnoxious  error
  2092.      routines and interpret the  return code for errors.   The biggest  ad-
  2093.      vantage to using these will be to those who are  also using the multi-
  2094.      ple record I/O  routines (FGet/PutRecA).   Note that  while these  are
  2095.      setup for TYPEd file I/O, they will work for FIELDed files, though the
  2096.      hassle involved with this is probably not worth the effort.   An error
  2097.      return indicates failure, generally an invalid handle was passed (6).
  2098.  
  2099.      See also FGetRecA/FSetRecA, FSetPtr.  See MFEDDEMO.BAS for examples.
  2100.  
  2101.  
  2102.  
  2103.  
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.                    Copyright (C) InfoSoft, 1986-1990, 1991               32
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.  
  2118.              Name: FRecGetA/FRecPutA        Type: FUNCTION
  2119.          Syntax: errc = FRecGetA(handle, Quan, size, SEG struct)
  2120.                  errc = FRecPutA(handle, Quan, size, SEG struct)
  2121.  
  2122.          These perform essentially the same function  as QB's GET# and PUT#
  2123.      but rather  than reading a single record, they  will fill a TYPE array
  2124.      with the number of  records designated by Quan.  That  is, rather than
  2125.      reading (or writing)  many records from  within a QB FOR...NEXT  loop,
  2126.      you can read as  many as desired in one pass and  much quicker, making
  2127.      it ideal for large database operations:
  2128.  
  2129.          errc = FGetRec(handle, 128, LEN(Emp(1)), Emp(1))
  2130.  
  2131.          This would read 128 records from  the file handle (starting at the
  2132.      current location) and  place them in the  TYPE array Emp beginning  at
  2133.      subscript 1.  The size of the  (TYPE) structure is passed so that  the
  2134.      functions can calculate the number of bytes to read.
  2135.  
  2136.          At this point, care  must be taken that the read  or write (trans-
  2137.      fer) request does not exceed 64k (Quan recs times Size of struct).  On
  2138.      the low end that means a max of 65536 1 bytes records or 32,768 2 byte
  2139.      records which  is pretty  reasonable.   On  the high  end, with  large
  2140.      structures, you will need to make  multiple 64k passes so the data  is
  2141.      read  from  (or written  to) the  correct  memory segment  (large type
  2142.      structures straddle or cross segment boundaries).  Example:
  2143.  
  2144.        ' assume LEN(RecStruct) = 512  bytes, and we want to read 256     ' 
  2145.      of them to fill a 128k array:
  2146.  
  2147.        ' read 64k (128 * 512) to RecStruct(1)
  2148.       errc = FGetRec(handle, 128, LEN(RecStruct(1)), RecStruct(1))
  2149.  
  2150.        ' read next 64k to RecStruct(129)
  2151.       errc = FGetRec(handle, 128, LEN(RecStruct(1)), RecStruct(129))
  2152.  
  2153.      Note that RecStruct subscripts would be 0 and 128 under OPTION BASE 0.
  2154.          The point is  that even though  it is  one array, the  destination
  2155.      segment  for  RecStruct(1) is  different  from that  of ResStruct(129)
  2156.      (though they have adjacent addresses).  Should you attempt this:
  2157.  
  2158.       ' try to read 128k (256 * 512 struct size)
  2159.       errc = FGetRec(handle, 256, LEN(RecStruct(1)), RecStruct(1))
  2160.      the  routine would indeed  read 128k but the  last 64k would overwrite
  2161.      the first 64k ie: records 128  to 256 would be stored at  RecStruct(1)
  2162.      to RecStruct (128).  We plan to modify this in the future  to properly
  2163.      recognize the end  of a segment so that  more than 64k can  be read in
  2164.      one call.
  2165.          The only likely return  code placed in errc, generally  signals an
  2166.      invalid handle (6) or a SHARE violation (5).
  2167.  
  2168.          NOTE: Records or  data are read from  the file at the  current DOS
  2169.      file pointer  position.   Use FSetPtr  to locate  this to the  desired
  2170.      spot: QB's SEEK may not always do the equivalent on random files.
  2171.  
  2172.      See also FGetRecA/FSetRecA, FSetPtr.  See MFEDDEMO.BAS for examples.
  2173.  
  2174.  
  2175.  
  2176.  
  2177.                    Copyright (C) InfoSoft, 1986-1990, 1991               33
  2178.  
  2179.  
  2180.  
  2181.  
  2182.  
  2183.  
  2184.              Name: FRename                  Type: FUNCTION
  2185.          Syntax: errc = FRename(oldf$, newf$)
  2186.  
  2187.          This allow you to rename a disk file.  Since a simple DOS function
  2188.      is used, both the source and destination files must reside on the same
  2189.      device (you may not move the file from one drive to another  with this
  2190.      function  - see  FMove, FReplicate  or FCopy  for  that).   Any return
  2191.      indicates an error such as an attempt to span drives.  Example:
  2192.          errc = FRename("foobar.new", "foobar.old")
  2193.  
  2194.  
  2195.  
  2196.              Name: FReplicate               Type: FUNCTION
  2197.          Syntax: errc = FReplicate(source$, dest$, buffer$)
  2198.  
  2199.          This works very similarly to FCopy, except the file  date and time
  2200.      are preserved on  the destination file.  As with FCopy and Fprint, you
  2201.      supply the buffer  by simply passing  a string or temporary  variable.
  2202.      Any errc return  indicates an  error such as  disk full, file  already
  2203.      exists and is Read Only, or disk is write protected. Eg:
  2204.          errc = FReplicate("foo.bar", "A:foo.bak", SPACE$(4096))
  2205.  
  2206.  
  2207.  
  2208.              Name: FSetPtr                  Type: FUNCTION
  2209.          Syntax: errc = FSetPtr(Fhandle, RecNo&, RecSize)
  2210.  
  2211.          Moves  the DOS  file pointer  to  a specified  location in  a file
  2212.      (usually to a  specific record in a random file) opened with a handle.
  2213.      Note that  RecNo is a  LONG INTEGER  so that very  large files  can be
  2214.      addressed.  This function is used  with FGetRec, FPutRec, FGetRecA and
  2215.      FPutRecA (qv) to locate the  DOS file pointer to a specific  location.
  2216.      Note that this  acts directly on  the DOS file  pointer and  therefore
  2217.      acts differently than QB's native SEEK  would (due to significant file
  2218.      buffering performed by the QB RTL  itself).  The use of this  function
  2219.      is a prerequisite to calls to FGetRec, FPutRec, FGetRecA and FPutRecA.
  2220.      See also FEOF, FRecGet, FRecPut, FRecGetA, FRecPutA.
  2221.  
  2222.          Example:  (TYPE Method)
  2223.  
  2224.          TYPE struct
  2225.              AName AS STRING * 25
  2226.              BStuff AS STRING * 15
  2227.              FooBar$ AS STRING * 15
  2228.          END TYPE
  2229.          DIM RecThing AS STRUCT
  2230.  
  2231.          RSIZE = LEN(RecThing)      ' do 1ce rather than many LEN calls
  2232.  
  2233.          OPEN datfil$ for RANDOM as #f LEN = RSize
  2234.          Fhandle = FILEATTR(f, 2)  ' Ask BASIC for handle of file
  2235.          ..
  2236.          ..
  2237.          errc = FSetPtr(FHandle, RecNo&, RSize)   ' seek to RecNo
  2238.          
  2239.          
  2240.  
  2241.  
  2242.  
  2243.                    Copyright (C) InfoSoft, 1986-1990, 1991               34
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.              Name: FTimeClear               Type: FUNCTION
  2252.          Syntax: errc = FTimeClear(fhandle)
  2253.  
  2254.          This allows you to  'clear' a file time so that  the time will not
  2255.      display when  using the DOS DIR command.  The  handle must be a valid,
  2256.      open handle using either FOpen or BASIC's OPEN and FILEATTR.  Example:
  2257.          fhandle = FILEATTR(BasNo, 2)
  2258.          errc = FTimeClear(fhandle)
  2259.  
  2260.  
  2261.  
  2262.  
  2263.              Name: FTimeGet/FTimeSet         Type: FUNCTION
  2264.          Syntax: errc = FTimeGet(fhandle, hour, min, sec)
  2265.                  errc = FTimeSet(fhandle, hour, min, sec)
  2266.  
  2267.          Like the name implies, these allow you to set or get the time of a
  2268.      file   - actually the last time it's directory entry was updated.  You
  2269.      must have  a valid,  open handle  for the  file via  FOpen or  BASIC's
  2270.      FILEATTR  function.   All  parameters must  be  integers and  the only
  2271.      likely error code is if the handle is not valid (file is closed).   If
  2272.      you perform I/O on a file AFTER setting the time, that time request is
  2273.      used when the directory entry is updated when the file is closed.  See
  2274.      also    FTimeClear.  Example:
  2275.        handle = FILEATTR(BasNo, 2)
  2276.        errc = FTimeSet(handle, 10, 10, 10)   ' set time to "10:10:10"
  2277.  
  2278.  
  2279.  
  2280.  
  2281.              Name: FuncResp                 Type: FUNCTION
  2282.          Syntax: RetCode = FuncResp
  2283.  
  2284.          Returns an integer representing a function key press.  The routine
  2285.      does not return until one is pressed.
  2286.          1 - 10  = F1 to 10
  2287.          11 - 20 = Shift + F1 to 10
  2288.          21 - 30 = Alt + F1 to 10
  2289.          31 - 40 = Control + F1 to 10
  2290.  
  2291.  
  2292.  
  2293.  
  2294.  
  2295.  
  2296.  
  2297.  
  2298.  
  2299.  
  2300.  
  2301.  
  2302.  
  2303.  
  2304.  
  2305.  
  2306.  
  2307.  
  2308.  
  2309.                    Copyright (C) InfoSoft, 1986-1990, 1991               35
  2310.  
  2311.  
  2312.  
  2313.  
  2314.  
  2315.  
  2316.  
  2317.  
  2318.              Name: FUnique                  Type: FUNCTION
  2319.          Syntax: errx = FUnique(fil$, attr, fhandle)
  2320.          This may also be invoked as FUniq
  2321.  
  2322.             This DOS  disk file function creates a file with a unique name,
  2323.      which makes it  ideal for scratch data files.  Rather than HOPING that
  2324.      "mydat.@@@" is a unique filename, FUNIQUE makes SURE that a file is in
  2325.      fact unique.  DOS  will create such a file in  the specified directory
  2326.      and open it with read write access with the attributes you specify.
  2327.  
  2328.             Furthermore, FUNIQUE  can, at  your option,  return the  actual
  2329.      file  NAME as well as the  handle.  Enter the  call with a string con-
  2330.      taining  the  desired  drive and path  where you want  the unique file
  2331.      created, BE SURE  to include a trailing backslash ("\")!    FUNIQ will
  2332.      return a  file handle or error code, and if you add 12 trailing spaces
  2333.      to the pathname,  it will return the  filename.  More often  than not,
  2334.      the unique name will be just  8 chars long, but if not, it  would only
  2335.      return part of the  name.  When the unique name IS  less than 12 char-
  2336.      acters  the name will  be padded with  spaces which allows  you to use
  2337.      BASIC's native RTRIM$ to fix it.
  2338.  
  2339.             NOTE: The unique file is OPEN  with a handle!  Subsequent  file
  2340.      access should be thru FWriteArray or FReadArray, or FCLOSE the handle,
  2341.      reopen the filename with BASIC's OPEN so as to access the filename via
  2342.      BASIC functions.
  2343.  
  2344.  
  2345.             NOTE: Use of FUNIQUE requires DOS 3.0 or greater.
  2346.  
  2347.  
  2348.          Example:
  2349.  
  2350.          DECLARE FUNCTION FUnique%(fil$, attrib%, fhandle%)
  2351.          ..
  2352.          ..
  2353.          tempfil$="C:\BIN\            "
  2354.          IF FUnique(fil$, 0, fhandle) THEN       ' path, normal file
  2355.             GOSUB InvalidInfo
  2356.          ELSE
  2357.             j=fclose(fhandle)                    ' close the handle
  2358.             tnum=FREEFILE                        ' get BASIC handle
  2359.             OPEN tempfil$ FOR APPEND AS #tnum    ' reopen file in  
  2360.          END IF                                  ' BASIC mode
  2361.       
  2362.  
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.  
  2372.  
  2373.  
  2374.  
  2375.                    Copyright (C) InfoSoft, 1986-1990, 1991               36
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.  
  2382.              Name: FWriteArry               Type: FUNCTION
  2383.          Syntax: errc = FWriteArry(SEG arry%, Fhandle%, BYTES%)
  2384.  
  2385.          FWriteArray writes data  from an  array directly to  a disk  file.
  2386.      The  file must  have  a valid  DOS File  Handle which  is accomplished
  2387.      either  by using FOpen  or FILEATTR on  a BASIC file  number.  'Chars'
  2388.      indicates the number of BYTES to write (remember that each elements in
  2389.      the array is 2 Bytes), upon return from the function BYTES is reset to
  2390.      the actual number written (in case of a lack of diskspace,  or invalid
  2391.      handle, the number written  will be less than that requested).    ERRC
  2392.      is set  to indicate any DOS error  encountered.  See the complimentary
  2393.      function FReadArry;  GLIBDEMO shows  a practical use  - binary  screen
  2394.      libs.       Example:
  2395.  
  2396.          DECLARE SUB SvScrn(SEG Arry%)
  2397.          DECLARE FUNCTION FWriteArry%(SEG arry%, Fhandle%, Bytes%)
  2398.          ..
  2399.          ..
  2400.          REDIM ScrnArry(2000)
  2401.          CALL SvScrn(ScrnArry(1))      ' save screen to array
  2402.          fil = FREEFILE                ' get next BAS file no
  2403.          OPEN "screens" FOR OUTPUT AS #fil
  2404.          handle = FILEATTR(fil,2)
  2405.          count = 4000                  ' 4000 bytes in 2000 elements
  2406.          errc = FWriteArry(ScrnArry(1), handle, count)
  2407.  
  2408.  
  2409.  
  2410.  
  2411.              Name: FWriteStr                Type: FUNCTION
  2412.          Syntax: errc = FWriteStr(SEG arry, Fhandle, Chars)
  2413.  
  2414.          FWriteStr writes  data from  a string  buffer directly  to a  disk
  2415.      file.  The file must have a valid DOS File Handle which is accomplish-
  2416.      ed  either by using FOpen or FILEATTR on a BASIC file number.  'Chars'
  2417.      indicates the  number of  characters to  write, upon  return from  the
  2418.      function Chars is  reset to the  actual number written  (in case of  a
  2419.      lack of diskspace, or invalid handle, the number written  will be less
  2420.      than that requested).     ERRC is set  to indicate any  DOS error  en-
  2421.      countered.  See the complimentary function FReadStr.   Example:
  2422.  
  2423.          DECLARE FUNCTION FWriteStr%(Buffer$, Fhandle%, chars%)
  2424.          ..
  2425.          ..
  2426.          LINE INPUT "Your name, age and occupation: ", info$
  2427.          fil = FREEFILE                  ' get next BAS file no
  2428.          OPEN fil$ FOR OUTPUT AS #fil
  2429.          handle = FILEATTR(fil,2)        ' convert File No to handle
  2430.          count = LEN(info$)              ' get number to write
  2431.          errc = FWriteStr(info$, handle, count)
  2432.  
  2433.  
  2434.  
  2435.  
  2436.  
  2437.  
  2438.  
  2439.  
  2440.  
  2441.                    Copyright (C) InfoSoft, 1986-1990, 1991               37
  2442.  
  2443.  
  2444.  
  2445.  
  2446.  
  2447.  
  2448.              Name: GetCmdTail               Type: FUNCTION
  2449.          Syntax: errc = GetCmdTail(tail$)
  2450.  
  2451.          Fetches the unparsed  command tail from  the PSP (Program  Segment
  2452.      Prefix).  Unlike BASIC's COMMAND$, this  is not converted to uppercase
  2453.      or  otherwise touched: it  is exactly as  the user typed  it, allowing
  2454.      your program to act on  case sensitive switches.  Initialize  tail$ to
  2455.      128 spaces or use GetCmdTLen (qv) to determine the size of the command
  2456.      tail.   Note that using this under the  QB environment will return the
  2457.      command line  to  invoke QB,  use QBLoaded  (qv) to  determine how  to
  2458.      interpret the tail$ return.  The  return code indicates possible error
  2459.      conditions:   -1 = String too short: there is not enough room to store
  2460.      the entire command tail in  the string.  In this case, GetCmdTail     
  2461.      returns as much as it can, and sets the error code.  See GetCmdTLen
  2462.  
  2463.  
  2464.  
  2465.              Name: GetCmdStr                Type: FUNCTION
  2466.          Syntax: CmdStr$ = GetCmdStr$
  2467.  
  2468.          This is a  hybrid of GetCmdTail  and ArgVar$ wherein the  function
  2469.      returns the unparsed command tail (like  GetCmdTail) and returns it as
  2470.      a function (like ArgVar).  This will most likely replace GetCmdTail in
  2471.      a future version.  Example:
  2472.          CmdLine$ = GetCmdStr$
  2473.  
  2474.  
  2475.  
  2476.  
  2477.              Name: GetCmdTLen               Type: FUNCTION
  2478.          Syntax: TailSize = GetCmdTLen
  2479.  
  2480.          Returns the  string  length required  to store  the command  tail.
  2481.      Allows you to initialize a string to the right  length prior to a call
  2482.      to  GetCmdTail rather  than assuming  128 and  then trimming it.   The
  2483.      return is either  the length required  or -3 indicating incorrect  DOS
  2484.      version (GetCmdTLen requires DOS 3.0).
  2485.        Example:   (assume we checked DOS Version already)
  2486.          size = GetCmdTLen                   ' get size required
  2487.          SELECT CASE size
  2488.              CASE  0                         ' no command line passed
  2489.                  PRINT "No Command Line !"
  2490.                  CLOSE
  2491.                  SYSTEM
  2492.  
  2493.              CASE IS > 0
  2494.                  tail$ = SPACE$(size)         ' initilize space
  2495.                  errc = GetCmdTail(tail$)     ' get tail
  2496.                  IF QBLoaded THEN              ' test if running under     
  2497.                                               '   the QB env
  2498.                      GOSUB AjustTail          ' adjust the return
  2499.                  END IF
  2500.                  GOSUB ParseArgs              ' get options
  2501.  
  2502.              CASE ELSE
  2503.                  PRINT "Weird error"
  2504.                  SYSTEM
  2505.          END SELECT
  2506.  
  2507.                    Copyright (C) InfoSoft, 1986-1990, 1991               38
  2508.  
  2509.  
  2510.  
  2511.  
  2512.  
  2513.  
  2514.  
  2515.              Name: GetCH                    Type: FUNCTION
  2516.          Syntax: ret$ = GetCH$(okay$)
  2517.  
  2518.             Return keystroke  from allowable  string of  selections.   Pass
  2519.      this  routine a  string of  okay  characters (in  upper case)  it will
  2520.      return which  of those were pressed.   GETCH ignores  input other than
  2521.      those  characters in the  okay$.  If  passed a null GETCH  string or a
  2522.      null return  string, GetCh will return  the first key pressed.   Addi-
  2523.      tionally,  2 features found  in GETCH  not in  other routines  of this
  2524.      nature, is that it will not get confused by any ANSI keyboard redefin-
  2525.      itions and  when used  on a  network, will  not hang  the terminal  or
  2526.      server when called.  Note: GetCh  purges the type ahead buffer  first.
  2527.      See also PGetCH, DialogBox.  Example:
  2528.          PRINT "Are You Sure?": ky$=" "
  2529.          CALL getch("YN", ky$)             ' allows input of Y or N only
  2530.  
  2531.  
  2532.  
  2533.              Name: GetDrv                   Type: FUNCTION
  2534.          Syntax: drv = GetDrv
  2535.  
  2536.             This gets the default disk drive.  It returns the ASCII code of
  2537.      the letter to avoid the confusion of drive numbering.  Converting to a
  2538.      character is simple with BASIC's CHR$ function.
  2539.  
  2540.  
  2541.              Name: GetDSeg                  Type: FUNCTION
  2542.          Syntax: DS = GetDSeg
  2543.  
  2544.             This is more  a development utility  than a usable  subroutine.
  2545.      This returns BASIC's  default Data  Segment (DS).   In tinkering  with
  2546.      calling C and routines from other languages, I've found this useful in
  2547.      making sure that the default data segment is not changed.
  2548.  
  2549.  
  2550.              Name: GetStack                 Type: FUNCTION
  2551.          Syntax: SP = GetStack
  2552.  
  2553.             Returns the  state of BASIC's stack.   This is  very helpful in
  2554.      determining what (if any) the stack should be set to, via a
  2555.      'CLEAR,,xxxx' statement at the start of your program.  The stack grows
  2556.      DOWNWARD with each  successive GOSUB, so  at strategic points in  your
  2557.      code, calling GETSTACK and comparing it  to the state of the STACK  at
  2558.      the  start of  the program,  aids  in determining  if you  do  need to
  2559.      include a stack statement at the start.
  2560.  
  2561.  
  2562.  
  2563.              Name: HALT                     Type: SUB
  2564.          Syntax: CALL HALT
  2565.  
  2566.          Stops the system  cold, requiring it to be shut off.   This can be
  2567.      handy in  security situations or when you want  to be sure that memory
  2568.      is cleared after  your program is  run.  This  is similar to  ShutDown
  2569.      except that there is no disk parking and no graphics.
  2570.  
  2571.  
  2572.  
  2573.                    Copyright (C) InfoSoft, 1986-1990, 1991               39
  2574.  
  2575.  
  2576.  
  2577.  
  2578.  
  2579.  
  2580.  
  2581.              Name: IACRead/IACSet/IACClear  Type: FUNCTION
  2582.          Syntax: errc = IACRead(s$, iopt)
  2583.                  errc = IACSet(s$, iopt)
  2584.                  errc = IACClear
  2585.  
  2586.          Your machine's BIOS reserves  a small amount of room  (very small)
  2587.      in low  memory specifically for Inter Application Communications ie to
  2588.      pass data between each  other.  This area is limited to  16 bytes, but
  2589.      this is enough to  pass or store a  12 character filename and up  to 2
  2590.      integer variables.   The problem  is that if  you store a  filename or
  2591.      string here for  a later program, and  before it can be  read, another
  2592.      program  uses this  area first,  our  info is  lost  (though very  few
  2593.      programs use this).   While a boot obviously destroys  anything stored
  2594.      in the IAC, we have stored things there and found them to be intact at
  2595.      the end of the day.
  2596.  
  2597.  
  2598.          To detect  any corruption of the IAC area,  we will use 2 bytes of
  2599.      the space to store a 16 bit  checksum.  When reading data from the IAC
  2600.      area if the checksum does not match, an error code of -3 is returned.
  2601.  
  2602.  
  2603.  
  2604.          IACSet:   errc = IACSet("string var", mopt)
  2605.                    Saves the string variable indicated as well as the
  2606.                    integer value to the IAC area.
  2607.  
  2608.  
  2609.          The string variable may be of any length up to 12  characters, but
  2610.      not more  than that.   If the  string passed is  larger than  12 char-
  2611.      acters, the  process is  not carried out  and an  error code of  -1 is
  2612.      returned.  This allows  at least a complete filename to be stored or a
  2613.      decent size string.
  2614.  
  2615.  
  2616.          IACRead:    errc = ReadIAC(stringvar$, intvar)
  2617.  
  2618.          Reads the  Intra-Application Communications  Area, and stores  the
  2619.      first 12  bytes into the string  variable, and fills  the integer var-
  2620.      iable with any value previously saved to the ICA area.  If a string of
  2621.      less than  12 spaces is passed, nothing is  returned and an error code
  2622.      of -2 is returned.
  2623.  
  2624.  
  2625.          IACClear       CALL IACCLear
  2626.  
  2627.          This  unambiguously overwrites  the string  area  of the  IAC with
  2628.      spaces and the integer area with zeroes and resets the checksum.
  2629.  
  2630.  
  2631.  
  2632.  
  2633.  
  2634.  
  2635.  
  2636.  
  2637.  
  2638.  
  2639.                    Copyright (C) InfoSoft, 1986-1990, 1991               40
  2640.  
  2641.  
  2642.  
  2643.  
  2644.  
  2645.  
  2646.              Name: INCR / DECR              Type: FUNCTION
  2647.          Syntax: result = INCR(x, y)
  2648.                  result = DECR(x, y)
  2649.  
  2650.             There  are  people out  there who  made  the tragic  mistake of
  2651.      getting  into  one of  those "other"  BASIC  dialects, and  are having
  2652.      trouble adapting to  QB.  INCR  and DECR are  meant to help  alleviate
  2653.      this.  If DECLARED as  a SUB, they will  work just like Turbo  BASIC's
  2654.      native functions of the same name.  
  2655.  
  2656.  
  2657.              Name: InsOn / InsOff           Type: FUNCTION
  2658.          Syntax: CALL InsOn : CALL InsOff
  2659.  
  2660.            This subroutine, simple puts the  keyboard into INSERT ON  state
  2661.      (INSON) or turns the insert toggle off (INSOFF).  Example:
  2662.              CALL InsOn
  2663.              CALL InsOff
  2664.  
  2665.  
  2666.  
  2667.              Name: INSTRI                   Type: FUNCTION
  2668.          Syntax: result = INSTRI(Start, FindIn$, LookFor$)
  2669.  
  2670.          This function is identical  to the BASIC native INSTR  except that
  2671.      it  is  case insensitive.    That is,  INSTRI will  return  an integer
  2672.      pointing to the first occurrence of either "CD" or "cd" in "ABCDEF" or
  2673.      "abcdef".  Like  INSTR, INSTRI allows the  use of a starting  point to
  2674.      begin the  search within the string to BE searched, unlike BASIC, this
  2675.      is not  optional, a 0  will point  to the same  starting point.   Like
  2676.      BASIC,  the  return is  a relative  pointer  from the  starting point.
  2677.      Further,  the routine will  recognize "?"  in the  search string  as a
  2678.      match-all wild card.   Example:
  2679.          DECLARE FUNCTION INSTRI%(start%, a$, b$)
  2680.          ..
  2681.          PRINT INSTRI(1, "AbCdEFGhiJkL", "cDe?")      ' prints 3
  2682.  
  2683.  
  2684.  
  2685.              Name(s): ISxxxxxx                 Type: FUNCTION(s)
  2686.          Syntax: status = IsXxxxx(c$)
  2687.  
  2688.          The 'izzy' collection provides for  assembler level replication of
  2689.      the highly useful IS??????? macros found in 'C'.  Where the 'C' macros
  2690.      work only on a single character, the InfoSoft assembler implementation
  2691.      works on either a character or a string.  When using a string however,
  2692.      a single non matching character forces a false return.  Example:
  2693.  
  2694.          IF IsAlpha("The quick brown fox is really a lazy dog.") THEN
  2695.              PRINT "All Alpha chars!"
  2696.          ELSE
  2697.              PRINT "Non alpha chars in string!"
  2698.          END IF
  2699.  
  2700.      In this example, the return is FALSE, the string is NOT all alpha
  2701.      characters - the  spaces and period in the string cause a zero (FALSE)
  2702.      return.  All the IZZY  functions return a 0 or  -1 based on the  func-
  2703.      tion.  The IZZY functions are:
  2704.  
  2705.                    Copyright (C) InfoSoft, 1986-1990, 1991               41
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.          IsASCII - Test if the string or character passed is 
  2714.                    > 0 and < 128 or  ASCII
  2715.  
  2716.          IsAlpha - Test if the string or character is between A-Z or       
  2717.                    a-z.
  2718.  
  2719.          IsAlNum - Test if the character or string is made of              
  2720.                    characters A-Z, a-z or 0-9.
  2721.  
  2722.          IsCntrl - Test if the string or character is in the range  0      
  2723.                    to 31 or 127.
  2724.  
  2725.          IsDigit - Test if the character or string is a decimal digit,     
  2726.                    (0-9).
  2727.  
  2728.          IsGraph - Test if the string or character is a printable.
  2729.                    The space is not considered a printable character.
  2730.                    In general,  this means the characters ASCII 33 to      
  2731.                    127.
  2732.  
  2733.          IsPrint - Same as IsGraph except the space is  allowed: ASCII     
  2734.                    32 to 127
  2735.  
  2736.          IsPunct - Tests for whether a string or character  is a           
  2737.                    punctuation mark: ~!@#$%^&*(){}[]:;"'?/><.,
  2738.  
  2739.          IsSpace - Test a character or string to see if it is a            
  2740.                    whitespace character (ASCII 9 to 13 or 32).
  2741.  
  2742.          IsUpper - Tests to see if the string or character is Upper        
  2743.                    case.  Very  useful when you want to preserve the       
  2744.                    case of some input or  want to avoid generating         
  2745.                    string garbage in reassigning  UCASE(x$) to a new,      
  2746.                    temporary variable.
  2747.  
  2748.          IsLower - Similar to IsUpper - tests for lower case.
  2749.  
  2750.         IsxDigit - Test for a string or character is a hex digit.
  2751.                    0-9, A-F and a-f are valid hexadecimal digits.
  2752.  
  2753.          IsGrafx - Tests if a string or character is a graphic box type
  2754.                    character.  These are ASCII 176 to 223.
  2755.  
  2756.          IsText  -  Determines if a string is text: alpha numeric, Carriage
  2757.                    return, line feed, FormFeed character or  graphic line  
  2758.                    characters (ASCII 10, 12, 13 and  176 to 223).  Typical-
  2759.                    ly,  this could be used on a string read from a file to 
  2760.                    determine the type of file it is.
  2761.          
  2762.               
  2763.          IsDocs -  Determines if a string is document format: All ASCII
  2764.                    characters 0  - 127, and box characters (alphanumeric,  
  2765.                    control characters and ASCII 176 to  223).  Typically,  
  2766.                    this could be used on a string read from  a file to     
  2767.                    determine if  the file is possibly some sort of word    
  2768.                    processing format.
  2769.  
  2770.  
  2771.                    Copyright (C) InfoSoft, 1986-1990, 1991               42
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.              Name: IsLeap                 Type: FUNCTION
  2779.          Syntax: LeapChk = IsLeap(Year)
  2780.  
  2781.          Returns a code indicating  if the year passed is a  leap year (-1)
  2782.      or not  (0).  Note that not  all years evenly divisible by  4 are leap
  2783.      years:  centennial years (1700, 1800, 1900) are NOT leap years  except
  2784.      those  that   are  divisible by  400  (1600, 2000,  2400).   IsLeap is
  2785.      accurate for years  1200 AD and after.
  2786.  
  2787.  
  2788.  
  2789.  
  2790.              Name: Julian                   Type: FUNCTION
  2791.          Syntax: JDay& = Julian&(month, day, year)
  2792.  
  2793.             Returns the _TRUE_  julian date for the  passed month/day/year.
  2794.      What many dating  schemes call "julian" is merely  an ordinal day code
  2795.      or  an ordinal code  serialized with the  year such as  89102 which is
  2796.      supposed to indicate  the 102nd day  of 1988.   Even worse, there  are
  2797.      some that return a SERIAL date by calculating the number of days since
  2798.      1/1/1.  These are invariably wrong since they do not take into account
  2799.      that  leap years are NOT  every 4 years (years such  as 1700, 1900 and
  2800.      2100 are not leap years); also they  tend to ignore that there were 11
  2801.      days suppressed in 1582  (you went to bed on Oct 4, you woke up on Oct
  2802.      15).
  2803.  
  2804.             A modified  form of serial  dating that  is widely  used is  to
  2805.      calculate the number of days elapsed since Jan 1, 1900.  This modified
  2806.      julian date method  is used by  LOTUS 1-2-3 (however they  erroneously
  2807.      recognize  1900 as  a leap  year probably  for simplicity).    This is
  2808.      generally  used  because invoicing  needs  and such  usually  need not
  2809.      extend back to  before 1900 and returns a smaller number (on the order
  2810.      of 32,000).
  2811.  
  2812.             A _TRUE_ julian date such as those returned by Julian&, repres-
  2813.      ent the number of days passed since Jan 1, 4713 BC.  Note that Julian&
  2814.      returns  a   long  integer  representing  this Julian  date.   Because
  2815.      Julian& will  not accept dates  before Jan  1, 0001  AD, the  smallest
  2816.      number returned is 1721424. That is, Julian does not convert BC dates.
  2817.  
  2818.  
  2819.            Such  a dating method  allows for  significant, long  range date
  2820.      calculations, such  as getting the date for a day x days in the future
  2821.      or x days ago.   Note that in passing  the year to Julian, nothing  is
  2822.      assumed.  That is, yr = 89 DOES NOT equate to 1989 but 88 AD.
  2823.          See JulianCvt for examples.
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.                    Copyright (C) InfoSoft, 1986-1990, 1991               43
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844.              Name: JulianCvt                Type: FUNCTION
  2845.          Syntax: errc = JulianCvt(Ser&, mo, day, yr)
  2846.  
  2847.            Reconstitutes a long  integer formulated by  Julian (qv) into  a
  2848.      valid date.  The  long integer is a _TRUE_ julian  date not an ordinal
  2849.      or serialized date from an arbitrary point.  The use of  Date, Julian,
  2850.      JualianCvt and/or  DFrmat allow for extensive date  calculations.  The
  2851.      function return  is non  zero for  unsupported dates  (such as any  BC
  2852.      date).  Example:
  2853.  
  2854.          REM 1.    Find the maturity date for a 90 Certificate of         '
  2855.            Deposit purchased 4/5/1989
  2856.  
  2857.          MatDate& = Julian(4, 5, 1989)  ' get julian date for 4/5/1989
  2858.          CALL JulianCvt(MatDate& + 90, m, d, y)  ' convert it + 90
  2859.  
  2860.          PRINT USING " CD matures in 90 days on ##_/##_/#### ";m;d;y
  2861.          CALL DFrmat(m, d, y, Mat$)
  2862.          PRINT "That day is ";Mat$
  2863.  
  2864.  
  2865.          REM  2. Calculate difference in 2 dates
  2866.  
  2867.        CALL Date(tm, td, ty)            ' get today's date
  2868.        Today& = Julian(td, tm, ty)      ' julian date for today
  2869.  
  2870.        DueDate& = Julian(dd, dm, dy)    ' julian date for a past date
  2871.  
  2872.        Diff& = ABS(Today& - DueDate&)  ' get difference in counts
  2873.  
  2874.  
  2875.       IF DueDate& > Today& THEN
  2876.           PRINT "Library book is not due for "; Diff& ; " more days."
  2877.       ELSE
  2878.           PRINT "Library Book is "; Diff&; " days overdue!"
  2879.           PRINT "   Pay up $"; (Diff& * LateChg); " or be shot!"
  2880.       END IF
  2881.  
  2882.  
  2883.  
  2884.  
  2885.  
  2886.  
  2887.  
  2888.  
  2889.  
  2890.  
  2891.  
  2892.  
  2893.  
  2894.  
  2895.  
  2896.  
  2897.  
  2898.  
  2899.  
  2900.  
  2901.  
  2902.  
  2903.                    Copyright (C) InfoSoft, 1986-1990, 1991               44
  2904.  
  2905.  
  2906.  
  2907.  
  2908.  
  2909.  
  2910.              Name: KBStuff                  Type: FUNCTION
  2911.          Syntax: errc = KBStuff(kb$)
  2912.  
  2913.          This stuffs the  keyboard buffer with  a string.   The default  KB
  2914.      buffer is 16 characters long, but many KB enhancers  are available and
  2915.      used to   enlarge this.  If this  enhancer stores the buffer start-end
  2916.      addresses in place of  the standard low memory location,  KBStuff will
  2917.      recognize it.  If the string  to stuff is longer than the  buffer, the
  2918.      FUNCTION  stuffs as much as the buffer allows and return a code of -2.
  2919.      If the string to stuff is NULL, the return code is -1.  In the case of
  2920.      -2   returns, you should  shorten clear the keyboard and/or parse  the
  2921.      stuff string to smaller sub strings.
  2922.  
  2923.          Note: Because of the way the BIOS expects to find the buffer start
  2924.      and end addresses, many  enhancers set up a secondary buffer  and feed
  2925.      the low-memory  buffer from  their own.   The  size of  the buffer  in
  2926.      characters is available from the function  KBBuffSize.  Also, for some
  2927.      reason, you may need to add a  trailing space if the last character is
  2928.      a carriage return.   Example:
  2929.          kb$ = "MASM KBStuff" + CHR$(13) + "exit" + CHR$(13) + " "
  2930.          SHELL     ' assemble the program, exit to main program.   Note    
  2931.               '  trailing space
  2932.  
  2933.  
  2934.  
  2935.  
  2936.              Name: KBBuffSize               Type: FUNCTION
  2937.          Syntax: size = KBBuffSize
  2938.  
  2939.          Return the recognized keyboard  buffer in low memory.   The buffer
  2940.      can be enlarged,  and moved from  the DOS default  area by a  keyboard
  2941.      enhancer.  In  most cases, KBBuffSize will not return the size of this
  2942.      enhanced/enlarged buffer because the KB  utility is 'feeding' the  low
  2943.      memory buffer  from it's  own buffer,  in  this case,  the default  16
  2944.      character size.   Use the return of this function to determine the max
  2945.      length of string allowed in KBStuff.   Example:
  2946.          MaxChars = KBBuffSize
  2947.  
  2948.  
  2949.  
  2950.              Name: KeyReady                 Type: FUNCTION
  2951.          Syntax: status = KeyReady
  2952.  
  2953.          Returns zero  or non zero  to indicate if a  key is waiting  to be
  2954.      read from the  keyboard input buffer.   The advantage to this  is that
  2955.      you can test  for the situation WITHOUT actually removing the key from
  2956.      the buffer - also for users of QB 4.00 and (a), it performs similar to
  2957.      SLEEP.   Example:
  2958.          IF KeyReady THEN GOSUB MenuFunc
  2959.  
  2960.  
  2961.  
  2962.  
  2963.  
  2964.  
  2965.  
  2966.  
  2967.  
  2968.  
  2969.                    Copyright (C) InfoSoft, 1986-1990, 1991               45
  2970.  
  2971.  
  2972.  
  2973.  
  2974.  
  2975.  
  2976.          Name: KeyLockCap, KeyLockNum,          Type: FUNCTION(s)
  2977.                KeyLockScrl, KeyLockIns 
  2978.          Syntax: chk = KeyLockCap%
  2979.                  chk = KeyLockNum%
  2980.                  chk = KeyLockScrl%
  2981.               chk = KeyLockIns%
  2982.  
  2983.          Checks a  specific keyboard  lock key  (CapsLock, NumLock,  Scroll
  2984.      Lock or  Insert) and returns non zero (-1)  if it is currently engaged
  2985.      or zero if it is not. See also KeyShift---.
  2986.  
  2987.  
  2988.  
  2989.             Name: KeyRateSet/KeyRateClr         Type: FUNCTION/SUB
  2990.          Syntax: errc = KeyRateSet(delay%, rate%)
  2991.                  CALL KeyRateClr
  2992.  
  2993.          AT systems  (as well  as  PCjr) have  the  ability to  adjust  the
  2994.      keyboard sensitivity rate,  (Typematic rate).   Sources indicate  that
  2995.      this is an AT capability as opposed to a 80286 feature, so I am unsure
  2996.      whether this is available to XT/286 systems.  KeyRateSet allows you to
  2997.      tailor the keyboard  response so that  your program can  appear to  be
  2998.      incredibly  responsive  and ZOOM  the  cursor  to and  fro  across the
  2999.      screen.    The Delay parameter controls  how long after a  key is held
  3000.      down before Typematic begins in the range 0 to 3:
  3001.                 0 - 250 milliseconds    2 - 750 milliseconds
  3002.                 1 - 500 milliseconds    3 - 1000 milliseconds (1 sec)
  3003.  
  3004.  
  3005.      The Rate parameter controls the Typematic speed or how many characters
  3006.      per second will be generated.  Valid parameters are 0 to 31; parameter
  3007.      speeds in characters per second (cps):
  3008.            00 = 30.7       08 = 15.0       16 = 7.5       24 = 3.7
  3009.            01 = 26.7       09 = 13.3       17 = 6.7       25 = 3.3
  3010.            02 = 24.0       10 = 12.0       18 = 6.0       26 = 3.0
  3011.            03 = 21.8       11 = 10.9       19 = 5.5       27 = 2.7
  3012.            04 = 20.0       12 = 10.0       20 = 5.0       28 = 2.5
  3013.            05 = 18.8       13 =  9.2       21 = 4.6       29 = 2.3
  3014.            06 = 17.1       14 =  8.6       22 = 4.3       30 = 2.1
  3015.            07 = 16.0       15 =  8.0       23 = 4.0       31 = 2.0
  3016.  
  3017.      To reset BIOS default delay and typematic rate, use KeyRateClr:
  3018.          CALL KeyRateClr
  3019.  
  3020.          Note that SMALLER parameters indicate  LARGER cps rates and there-
  3021.      fore FASTER keyboard rates.  Also,  passing invalid parameters seem to
  3022.      produce no  change in  the TypeMatic  rate (the  BIOS seems  to ignore
  3023.      them).  Neither of these routines will execute if a 80286 processor is
  3024.      not present and KeyRateSet will return an error code of -1 if there is
  3025.      no 286 present.
  3026.  
  3027.  
  3028.  
  3029.  
  3030.  
  3031.  
  3032.  
  3033.  
  3034.  
  3035.                    Copyright (C) InfoSoft, 1986-1990, 1991               46
  3036.  
  3037.  
  3038.  
  3039.  
  3040.  
  3041.  
  3042.         Name: KeyShiftAlt, KeyShiftCtrl         Type: FUNCTION(s)
  3043.               KeyShiftRgt, KeyShiftLft 
  3044.               Syntax: chk = KeyShiftAlt%
  3045.                       chk = KeyShiftCtrl%
  3046.                       chk = KeyShiftRgt%
  3047.                       chk = KeyShiftLft%
  3048.  
  3049.          Checks a  specific shift  key (Alternate,  Control, Left-Shift  or
  3050.      Right-Shift) and returns  non zero (-1) if it is  currently pressed or
  3051.        zero if it is not. See also KeyLock---.
  3052.  
  3053.  
  3054.  
  3055.  
  3056.              Name: LCount                   Type: FUNCTION
  3057.          Syntax: NumLines = LCount(fhandle, buffer$)
  3058.          This may also be called as LineCount.
  3059.  
  3060.             This  is a nifty routine to swiftly  scan an existing disk text
  3061.      file for ASCII 13 (carriage return)  and count them (which is a  short
  3062.      cut way  of  determining lines  in a  file...).    This  is handy  for
  3063.      sequential file I/O where  you might want to inform the  user how long
  3064.      processing will  take or  to replace  a  loop thaty  includes a  BASIC
  3065.      function evaluation:
  3066.  
  3067.      WHILE NOT EOF(x)              ' BASIC will execute EOF function
  3068.         ....                       ' many times
  3069.      WEND 
  3070.          
  3071.  
  3072.      FOR x=1 to NumLines           ' no basic function!
  3073.          ....
  3074.      NEXT x loop.
  3075.  
  3076.             LCOUNT is  a function  that requires  a valid  file handle  via
  3077.      FOpen (or the return from FILEATTR)  and a scratch buffer - typically,
  3078.      you will find that a buffer of 4096 characters is sufficient).
  3079.  
  3080.  
  3081.          An  attempt to  LCOUNT a standard  DOS handle (1-4)  is trapped by
  3082.      LCount and  will return an error of -1.   LCOUNT is incredibly fast: a
  3083.      50K test file takes only .5 seconds to count on a 286 system.
  3084.  
  3085.  
  3086.          LCount leaves  the DOS  file pointer at  the end  of the  file, so
  3087.      prior subsequent INPUT and LINE INPUT statements should be preceded by
  3088.      a BASIC SEEK or a GLib SetFPtr to relocate it to where you want it.   
  3089.  
  3090.  
  3091.  
  3092.  
  3093.  
  3094.  
  3095.  
  3096.  
  3097.  
  3098.  
  3099.  
  3100.  
  3101.                    Copyright (C) InfoSoft, 1986-1990, 1991               47
  3102.  
  3103.  
  3104.  
  3105.  
  3106.  
  3107.  
  3108.              Name: LNameF                   Type: FUNCTION
  3109.          Syntax: SwappedName$ = LNameF$(text$)
  3110.  
  3111.            This data entry routine is handy for rearranging names from some
  3112.      other source  to convert them  to "Lastname, FirstName".   It works on
  3113.      names of all types, those with middle initials, just first and  middle
  3114.      initials, multiple middle names.   It does not work correctly  on Jrs,
  3115.      people who are  the II, III  or IV (ad  nauseum).  In  this case,  I'd
  3116.      suggest using BASIC's INSTR and LEFT$ to trim off the Jr or II etc and
  3117.      append it after the LNAMEF call.
  3118.  
  3119.            All that is required  is that the name have  one single trailing
  3120.      space and  another space  where the names  get swapped.   The function
  3121.      will fail and return a -1 if either condition is found to be not true.
  3122.  
  3123.      Examples:
  3124.  
  3125.      "Mary Beth J. Sandra Brooks " =>  "Brooks, Mary Beth J. Sandra"
  3126.      "P. T. Barnum Bailey "        =>  "Bailey, P. T. Barnum"
  3127.      "Thomas Q. McFly III "        =>  "III, Thomas Q. McFly"
  3128.      "John Public"                 =>  "John Public"  
  3129.                               This one fails due to no trailing space$
  3130.  
  3131.  
  3132.  
  3133.  
  3134.              Name: LPrintX                  Type: Function
  3135.          Syntax: errc = LPrintX(text$, printer)
  3136.  
  3137.          Send the string 'text$' to the designated printer (1 - 4).   After
  3138.      each character is printed, it tests to see if it is online and if not,
  3139.      aborts the operation  and returns a non  zero error code.   This works
  3140.      fine  for Out of  Paper and Power  Off situations, but  those that are
  3141.      simply offline,  it may  take quite  a while  for it  to timeout  (See
  3142.      LPTDelay).
  3143.  
  3144.  
  3145.  
  3146.  
  3147.              Name: LPTDelay                 Type: SUB
  3148.          Syntax: CALL LPTDelay(printer, DelayValue)
  3149.  
  3150.          The system BIOS stores a  Time-Out value in low memory that  tends
  3151.      to represent a relative  number of seconds required before  a time-out
  3152.      can be detected.   The actual value  in low memory tends  to represent
  3153.      seconds on 8088/8086  machines and (seconds/4)  on 286 systems.   This
  3154.      value  is usually 20  meaning anything  from a 20  second to 60  or 70
  3155.      second delay for  a timeout.  The  sub program LPTDelay allows  you to
  3156.      alter this  value  which  can be  pretty  handy,  particularly  during
  3157.      testing  and debugging of    printer  I/O routines and  error handlers
  3158.      (see LPRINTX).  The new DelayValue is placed in the time-out table for
  3159.      the printer specified and  would be used in future  (parallel) printer
  3160.      operations.  You should either restore this value to 20 or reboot when
  3161.      done.   Remember, that  value is not  actual seconds  to time-out, but
  3162.      lower numbers will timeout more quickly than higher numbers.
  3163.  
  3164.  
  3165.  
  3166.  
  3167.                    Copyright (C) InfoSoft, 1986-1990, 1991               48
  3168.  
  3169.  
  3170.  
  3171.  
  3172.  
  3173.  
  3174.              Name: MCsrInc/MCsrDec          Type: SUB
  3175.          Syntax: CALL MCsrInc
  3176.                  CALL MCsrDec
  3177.  
  3178.             Mouses are  curious things.   Each call to  turn off  the mouse
  3179.      cursor requires an  equal number of  cursor-on calls to redisplay  the
  3180.      cursor.   The  mouse driver tracks  what is called  an internal cursor
  3181.      flag.  Each call to turn  off the cursor decrements the counter,  each
  3182.      cursor-on call increments it and if (and only if) the internal flag is
  3183.      0,  the cursor is  displayed.   Therefore each  call to  decrement the
  3184.      flag, needs one increment call if the cursor is to be  displayed.  And
  3185.      this does NOT  work the other  way, if  the cursor is  on (flag=0)  an
  3186.      additional call to increment the flag has no effect.  Finally, we have
  3187.      no access to be able to read what the cursor flag is to know  how many
  3188.      MCSRINC calls we need to make to display the cursor.
  3189.  
  3190.             If you are  new to  mouse programming, take  care updating  the
  3191.      screen  with the  mouse cursor on,  it can leave  little reverse video
  3192.      blocks all over, and at times, doing a MSETXY with the cursor  on will
  3193.      produce 2 cursors: one at the old and another at the new location.  To
  3194.      avoid this, turn the mouse cursor off before screen updates, including
  3195.      (indeed,  especially with) screen saves  and restores and forced mouse
  3196.      cursor relocations.
  3197.  
  3198.             MCSRINC and MCSRDEC increment or decrement the cursor.  Knowing
  3199.      what you do now, it would  make sense to track a copy of  the internal
  3200.      flag in your program.  If in the course of your program you want to BE
  3201.      SURE that  the cursor is  on or off,  performing a  call to MCSRON  or
  3202.      MCSROFF will do so.  However in so doing, the mouse is reset: x  and y
  3203.      range  limits,  cursor masks,  mickey factors,  the  works.   SEE ALSO
  3204.      MCSRON, MCSROFF
  3205.  
  3206.          Example:                 Logical Equivalence
  3207.  
  3208.          CALL MCsrInc             ' InternalFlag=InternalFlag + 1
  3209.                                   ' IF InternalFlag=0 THEN ShowCursor
  3210.  
  3211.          CALL MCsrDec             ' InternalFlag=InternalFlag - 1
  3212.                                   ' IF InternalFlag<>0 THEN HideCursor
  3213.  
  3214.  
  3215.  
  3216.  
  3217.              Name: MCsrOn / MCsrOff         Type: SUB
  3218.          Syntax: CALL MCsrOn
  3219.  
  3220.             Reset the mouse  to power on  state and force an  unconditional
  3221.      cursor on or off.  This Unconditional Cursor On function also initial-
  3222.      izes the cursor thus erasing XY ranges, and resetting the mouse cursor
  3223.      location.  See also MCSRINC/MCSRDEC.
  3224.  
  3225.  
  3226.  
  3227.  
  3228.  
  3229.  
  3230.  
  3231.  
  3232.  
  3233.                    Copyright (C) InfoSoft, 1986-1990, 1991               49
  3234.  
  3235.  
  3236.  
  3237.  
  3238.  
  3239.  
  3240.  
  3241.  
  3242.  
  3243.              Name: MGetXY                   Type: SUB
  3244.          Syntax: CALL MGetXY(TextFlag, Mx, My)
  3245.  
  3246.             As you  might expect, this gets the current X,Y location of the
  3247.      mouse.  The location of  the text cursor has  no bearing on what  this
  3248.      returns.  Nor does  it matter if the mouse cursor is on or off: MGetXY
  3249.      returns  the CURRENT location  of the cursor, NOT  the LAST SEEN loca-
  3250.      tion.  Unlike some "other" QB libraries, MGetXY and MSetXY  (see also)
  3251.      use and  act upon either 80x25 coordinates or  pixel mode thru the use
  3252.      of a flag.   Setting TextFlag to 1  instructs the code to  convert the
  3253.      return to 80x25 coordinates, 0 returns pixel based locations.
  3254.       Example:
  3255.  
  3256.          REM get mouse cursor
  3257.          CALL MGetXY(1, MouseRow, MouseCol)
  3258.  
  3259.  
  3260.  
  3261.  
  3262.  
  3263.              Name: MLong / MNorm            Type: FUNCTION
  3264.          Syntax: CALL Mlong  : CALL MNorm
  3265.  
  3266.             Control  of the sensitivity of the  mouse is the ratio by which
  3267.      one mouse inch  moves x number of  characters or pixels on  the screen
  3268.      and is called the Mickey Factor.
  3269.             The default Mickey Factor of the New Microsoft Mouse is about 2
  3270.      inches per 80 horizontal characters and 1 inch per 25 rows vertically.
  3271.      MLONG alters the  Mickey Factor so that  it takes about twice  as much
  3272.      desk space to travel the same  screen distance: 4 inches horizontally,
  3273.      2  inches vertically, while MNORM resets the Mickey back to 2 horizon-
  3274.      tally, 1 vertically, as does a call to MCSRON (qv).
  3275.  
  3276.  
  3277.  
  3278.  
  3279.  
  3280.              Name: MRelease/MPress          Type: SUB(s)
  3281.          Syntax: CALL MRelease(lft, rgt)
  3282.  
  3283.             These mouse routines return the number of mouse button RELEASES
  3284.      or PRESSES  since the  last time  the mouse  driver was  polled.   One
  3285.      obvious use of  these two routines is to  poll the driver to  see if a
  3286.      double click  has been executed  since the  last poll (say,  while the
  3287.      program was off doing a disk access or such).   Example:
  3288.          CALL MRelease(lbutton, rbutton)
  3289.          CALL MPress(lbutton, rbutton)
  3290.  
  3291.  
  3292.  
  3293.  
  3294.  
  3295.  
  3296.  
  3297.  
  3298.  
  3299.                    Copyright (C) InfoSoft, 1986-1990, 1991               50
  3300.  
  3301.  
  3302.  
  3303.  
  3304.  
  3305.  
  3306.  
  3307.  
  3308.  
  3309.              Name: MSetXRng / MSetYRng      Type: SUB
  3310.          Syntax: CALL MSetXRng(TextFlag, min, max)
  3311.                  CALL MSetYRng(TextFlag, min, max)
  3312.  
  3313.             MSetXRng  and  MSetYRng  allow you  to  limit  the  minimum and
  3314.      maximum  X and Y range that the mouse  cursor is to be allowed to roam
  3315.      in.  A use for this would be to limit the mouse to an area in a window
  3316.      or  a menu.  Further, this routine is  suitable for use in either text
  3317.      or graphics modes thru a flag.    Example:
  3318.  
  3319.      REM limit mouse area to a box of 5,1 to 12,40 in 80x25 mode:
  3320.          TextMode = 1
  3321.          MinR = 5: MaxR = 12
  3322.          CALL MSetXRng(TextMode, MinR, MaxR)
  3323.          MinC = 1: MaxC = 40
  3324.          CALL msetyrng(TextMode, MinC, MaxC)
  3325.  
  3326.  
  3327.  
  3328.  
  3329.              Name: MSetXY                   Type: SUB
  3330.          Syntax: CALL MSetXY(TFlag, row, col)
  3331.  
  3332.            This is the simple inverse of  MGetXY, setting the current mouse
  3333.      cursor position.  MSetXY works off of either 80 x 25 based coordinates
  3334.      (if TFlag = 1) or pixel based locations.
  3335.             Note that the mouse cursor normally  seems to default to center
  3336.      screen (12,40) with a simple cursor on call (MCSRINC, MCSRON).
  3337.          Example:     ' set Mcursor position to row 20, column 60
  3338.          CALL MSetXY(1, 20, 60)
  3339.  
  3340.  
  3341.  
  3342.  
  3343.              Name: MSMouse                  Type: SUB
  3344.          Syntax: CALL MSMouse(ax, bx, cx, dx)
  3345.  
  3346.          While  the  mouse  functions  incorporated  into GLIB  are  fairly
  3347.      comprehensive, there may be times when you want to execute one  of the
  3348.      more esoteric ones like cursor customization.   MSMouse provides for a
  3349.      way of executing any general mouse  function directly to the Microsoft
  3350.      Mouse Driver.   AX, BX, CX and DX are  the registers (also referred to
  3351.      as M1, M2, M3 and M4 in some mouse references).  AX (or M1) is used to
  3352.      indicate the function  to execute and the others may need to be loaded
  3353.      with  other required parameters.   After executing  the interrupt, the
  3354.      parameters  are replaced with the  register contents after that inter-
  3355.      rupt.  If you do not have a decent mouse reference there are a  few on
  3356.      the Information Booth - or call and leave a note and we will look it
  3357.      up for you.
  3358.  
  3359.  
  3360.  
  3361.  
  3362.  
  3363.  
  3364.  
  3365.                    Copyright (C) InfoSoft, 1986-1990, 1991               51
  3366.  
  3367.  
  3368.  
  3369.  
  3370.  
  3371.  
  3372.  
  3373.  
  3374.              Name: MSetCsr                  Type: SUB
  3375.          Syntax: CALL MSetCsr
  3376.  
  3377.             This is a rather  specialized routine for  the mouse.  Some  of
  3378.      the less compatible mice require  a little tweaking to get  the cursor
  3379.      to display.   If you have trouble getting a cursor to display, calling
  3380.      MSetCSR should set the mask so that it does display when the cursor is
  3381.      on.  It appears to have no ill effect on mice who do not need it.
  3382.  
  3383.  
  3384.  
  3385.  
  3386.              Name: MStatus                  Type: SUB
  3387.          Syntax: CALL MStatus(lft, rgt)
  3388.  
  3389.            This returns  a 0/1 indicating if the left or right mouse button
  3390.      is currently being pressed.
  3391.  
  3392.  
  3393.  
  3394.  
  3395.              Name: MType                    Type: FUNCTION
  3396.          MouseType = MType
  3397.  
  3398.             This  routine  returns whether  a mouse  exists  or not  as the
  3399.      number of mouse  buttons.  Naturally, that  means 0, 2  and 3 are  the
  3400.      only MTYPE returns you should expect.
  3401.          Example:
  3402.          MouseExist = MType
  3403.          IF MouseExist THEN
  3404.             ..
  3405.             ..
  3406.          END IF
  3407.  
  3408.  
  3409.  
  3410.  
  3411.  
  3412.  
  3413.  
  3414.  
  3415.  
  3416.  
  3417.  
  3418.  
  3419.  
  3420.  
  3421.  
  3422.  
  3423.  
  3424.  
  3425.  
  3426.  
  3427.  
  3428.  
  3429.  
  3430.  
  3431.                    Copyright (C) InfoSoft, 1986-1990, 1991               52
  3432.  
  3433.  
  3434.  
  3435.  
  3436.  
  3437.  
  3438.              Name: MemCompA                 Type: FUNCTION
  3439.          Syntax: code = MemCompA(SEG Arry1, SEG Arry2, words)
  3440.  
  3441.          Compares the listed  number of WORDS  of two memory sections  (ty-
  3442.      pically  this would  be  elements of  2 arrays)  and returns  the BYTE
  3443.      offset where they mismatch or 0 if the 2 things to compare  are ident-
  3444.      ical.   This can be helpful in  UnDo type functions or to determine if
  3445.      I/O in a SUB altered an array. See also MemCompV.  Eg:
  3446.      REDIM AArray(10), BArray(10)
  3447.      code = MemCompA(AArray(1), BArray(1), 20)   ' 10 * 2 = 20 bytes
  3448.      IF Code THEN
  3449.          PRINT "Arrays are not identical"
  3450.      END IF
  3451.  
  3452.  
  3453.  
  3454.  
  3455.              Name: MemCompV                 Type: FUNCTION
  3456.          Syntax: offs = MemCompV(SEG Arry)
  3457.  
  3458.          Compares  the video display  to the next  4000 bytes  in the array
  3459.      passed and returns  an offset of  where they differ  or 0 if  they are
  3460.      identical.   Snow is checked for if a  CGA is detected.  Note that the
  3461.      return  will  indicate a  screen OFFSET  from  (1,1) where  the screen
  3462.      differs from the array.  Note also that the array offset passed can be
  3463.      any position.  The returned  value is a WORD offset that  allows us to
  3464.      easily convert to Row/Column coordinates.  See also MemCompA. 
  3465.      Example:
  3466.  
  3467.          scrn = 4001                   ' point to screen offset 3
  3468.          CALL SaveScrn(Array(scrn))    ' save video to position 3
  3469.          GOSUB DoStuff
  3470.          offset = MemCmpV(Array(scrn))
  3471.          IF offset THEN
  3472.             PRINT "Screen altered at offset: ";offset
  3473.          END IF
  3474.  
  3475.  
  3476.  
  3477.                          
  3478.  
  3479.              Name: MemMove                  Type: SUB
  3480.          Syntax: CALL MemMove(SEG src, SEG dest, words)
  3481.  
  3482.          MemMove works like the standard 'C' function of the same name - it
  3483.      moves a  block of  memory from  the source  to the  destination.   One
  3484.      excellent use  for this is  to replicate arrays.   Make sure  that the
  3485.      destination array  is large enough for the number  of bytes to copy so
  3486.      as  not to write to an unallocated block of memory.   Example:
  3487.      DECLARE SUB MemMove(SEG Src%, SEG Dest%)
  3488.        ..
  3489.        ..
  3490.      REDIM Arry1(2000), Arry2(2000)
  3491.        ..
  3492.      CALL MemMove (Arry1(1), Arry(2), 2000)   ' 2000 = 2000 elements
  3493.  
  3494.  
  3495.  
  3496.  
  3497.                    Copyright (C) InfoSoft, 1986-1990, 1991               53
  3498.  
  3499.  
  3500.  
  3501.  
  3502.  
  3503.  
  3504.  
  3505.              Name: MenuCtrl                 Type: FUNCTION
  3506.          Syntax: code = MenuCtrl
  3507.  
  3508.          MENUCTRL  is  a keyboard  / menu  control  module that  is totally
  3509.      network compatible to  trap specific keys.   As such, it is  ideal for
  3510.      menu driven routines.   When called,  the routine intercepts all  key-
  3511.      board activity exiting only if a number key or function key is pressed
  3512.      - any other input  is ignored.  MENUCTRL returns the value  of the key
  3513.      or  function key pressed,  ie '1' and/or  '[F1]' return  1, '2' and/or
  3514.      '[F2]' returns 2 etc.  Pressing [Esc] returns 15.    
  3515.  
  3516.  
  3517.  
  3518.  
  3519.              Name: MergeArray               Type: SUB
  3520.          Syntax: CALL MergeArray(SEG Mask, SEG Dest, Words)
  3521.  
  3522.          Given two  arrays (presumably  screen images),  all characters  in
  3523.      MASK array are transferred  to the destination array EXCEPT  when they
  3524.      are a space.  One use for this would be to superimpose a grid or other
  3525.      mask over an image then ScrnRest it to the video for reference points.
  3526.      If you retain  an unaltered image of  it, you could allow  the user to
  3527.      flip back and forth.  Pseudo  Animation is another possibility.   Note
  3528.      that the number of WORDS or  INTEGERS is used rather than BYTES.   See
  3529.      also MergeScrn.  Example:
  3530.          DECLARE SUB MergeArray(SEG Mask, SEG Dest, ByteCnt)
  3531.          REDIM Scrns(2000), Grid(2000)       ' allocate memory
  3532.          GOSUB FillGrid                      ' put lines in Grid()
  3533.  
  3534.          GOSUB GetScrn                       ' put whatever in array
  3535.          CALL MergeArray(Grid(1), Scrns(2001), 2000)
  3536.          ' Merge Grid over Screen
  3537.          CALL RestScrn(Scrns(1))             ' display end result
  3538.  
  3539.  
  3540.  
  3541.  
  3542.  
  3543.  
  3544.  
  3545.              Name: MergeScrn                Type: SUB
  3546.          Syntax: CALL MergeScrn(SEG Mask)
  3547.  
  3548.          This is similar to  MergeArray except the mask is  merged directly
  3549.      to the screen and 4000 bytes is assumed.   Example:
  3550.          DECLARE SUB MergeScrn(SEG Mask%)
  3551.          REDIM Grid(2000)              ' allocate memory
  3552.          GOSUB FillGrid                ' put lines in Grid()
  3553.  
  3554.          CALL MergeScrn(Grid(1))       ' place GRID over CRT display
  3555.  
  3556.  
  3557.  
  3558.  
  3559.  
  3560.  
  3561.  
  3562.  
  3563.                    Copyright (C) InfoSoft, 1986-1990, 1991               54
  3564.  
  3565.  
  3566.  
  3567.  
  3568.  
  3569.  
  3570.              Name: MFED                     Type: FUNCTION     (BASIC)
  3571.          Syntax: FCode = MFed(ed$, fsiz, Macro$())
  3572.  
  3573.          (Complete documentation and use is in MACROxx.DOC)
  3574.          This is a  very comprehensive text  input routine that allows  you
  3575.      extensive control over user input.  It is used to exert  total control
  3576.      over the user's input, recognizing all cursor and function keys.
  3577.      Ed$      - string to edit
  3578.      fsiz     - maximum length allowed
  3579.      Macro$() -  array of strings to be invoked with [Alt- ] key           
  3580.               strokes.
  3581.      Be sure to carefully read MACROxx.DOC for set up of the COMMON block!
  3582.  
  3583.  
  3584.  
  3585.  
  3586.              Name: MHZ                      Type: FUNCTION
  3587.          Syntax: speed = MHZ
  3588.  
  3589.             This returns the approximate, effective MegaHertz the system is
  3590.      run at.   Sound vague  enough?  This  return is  the result of  a very
  3591.      quick benchmark.  It  is "approximate" and "effective" Mhz  because it
  3592.      will be  off a little  depending on the number  of wait states  of the
  3593.      machine, and some faster PC clones return falsely high numbers.
  3594.             MHZ  returns the  speed factor  as a  whole number:  that is  a
  3595.      return of 935 means an effective MHZ speed of 9.35.  Divide the return
  3596.      by 100.   It is  advised that you  cross reference the  speed with the
  3597.      chip: if MHZ returns  1400 but CPUINFO  indicates a 8088 machine,  you
  3598.      know the speed is wrong and that the PC is more likely 8 to 10 MHz.
  3599.  
  3600.  
  3601.  
  3602.  
  3603.              Name: MilliDelay               Type: SUB
  3604.          Syntax: CALL MilliDelay(millisecs)
  3605.  
  3606.          MilliDelay works like DELAY in that it enables you to insert
  3607.      controllable delays  or slow downs  into your  code for  effect or  to
  3608.      allow the end user time to digest the screen.  This halts processing a
  3609.      given number of  milliseconds (100 milliseconds minimum) and works out
  3610.      great when a full second is too long.  Example:   CALL mdly(100)      
  3611.       ' delay .1 seconds
  3612.  
  3613.  
  3614.  
  3615.  
  3616.  
  3617.  
  3618.  
  3619.  
  3620.  
  3621.  
  3622.  
  3623.  
  3624.  
  3625.  
  3626.  
  3627.  
  3628.  
  3629.                    Copyright (C) InfoSoft, 1986-1990, 1991               55
  3630.  
  3631.  
  3632.  
  3633.  
  3634.  
  3635.  
  3636.              Name: NFrmat                   Type: FUNCTION     (BASIC)
  3637.          Syntax: errc = NFrmat(numst$, mode, point)
  3638.  
  3639.          This routine allows  for extensive numeric string processing.  You
  3640.      can format a numeric string to pre  determined formats such as 7 or 10
  3641.      digit phone numbers, social security or an account number type format.
  3642.      Parameters:
  3643.          numst$ =  string to process (presumably numeric)
  3644.          p = position  of a single "-"  for mode 4 (account number         
  3645.      numbers...)   
  3646.          m = mode or level of processing to perform:
  3647.          Mode 1 = Seven digit phone number ie: ###-####
  3648.               2 = Formatting to 10 phone type ie: (xxx) xxx-xxxx
  3649.               3 = Formatting to social security style ie: xxx-xx-xxxx
  3650.               4 = Format with "-" in position p.
  3651.  
  3652.           To get (316)-684-8744 out of 3166848744:
  3653.           errc = NFrmat(st$, 2, 0)
  3654.  
  3655.          Mode 4 Example:
  3656.          INPUT "Account Number:", st$       ' they key in 3145678
  3657.          errc = NFrmat(st$, 4, 3)
  3658.          PRINT st$                          ' output would be 31-45678
  3659.  
  3660.          Errc returns -1 on an unknown mode or format code.
  3661.  
  3662.  
  3663.  
  3664.  
  3665.              Name: NLON / NLOFF                Type: FUNCTION
  3666.          Syntax: CALL NLOn : CALL NLOff
  3667.  
  3668.          Sets the Keyboard Num Lock key to on (NLON) or off (NLOFF).
  3669.  
  3670.  
  3671.  
  3672.              Name: NoBoot                   Type: SUB
  3673.          Syntax: CALL NoBoot(func)
  3674.  
  3675.          This "steals" the keyboard interrupt to watch for the simultaneous
  3676.      press of Ctrl-Alt-Del, which it promptly  disregards.  Since this does
  3677.      act to  replace the keyboard  handler, it  is imperative that  you un-
  3678.      install  it before your  program terminates,  as well  as part  of any
  3679.      error handler you have and certainly before hitting Ctrl-Break to drop
  3680.      to QB editor level when running in the QB environment.  Function 0 un-
  3681.      installs NoBoot, any  non zero value  installs it -  take care not  to
  3682.      install multiple copies!  Example:
  3683.          CALL NoBoot(1)                  ' install it
  3684.          CALL NoBoot(0)                  ' uninstall it
  3685.  
  3686.  
  3687.  
  3688.  
  3689.  
  3690.  
  3691.  
  3692.  
  3693.  
  3694.  
  3695.                    Copyright (C) InfoSoft, 1986-1990, 1991               56
  3696.  
  3697.  
  3698.  
  3699.  
  3700.  
  3701.  
  3702.              Name: Painter                  Type: SUB
  3703.          Syntax: CALL Painter(Trow, Lcol, Brow, Rcol, newattr)
  3704.  
  3705.          This re-colors the specified area of the screen with the new color
  3706.      specified in  newattr.    This is ideal and  well suited for  bar menu
  3707.      type functions to  recolor or hi-light  the current selection, or  for
  3708.      modifying a color screen for mono use  (Turn off the video, repaint it
  3709.      and turn it back on - then SAVE it for future use!)  Example:  Recolor
  3710.      right half of screen to yellow on red:
  3711.          CALL Painter(1, 40, 25, 80, 78)
  3712.  
  3713.  
  3714.  
  3715.              Name: ParseFileSpec            Type: FUNCTION
  3716.          Syntax: errc = ParseFileSpec(raw$, drv$, path$, fil$, ext$)
  3717.  
  3718.          Given a legal  filename, this  will parse it  into it's  component
  3719.      parts and devoid of trivial punctuation  (colons and dots are removed,
  3720.      backslashes are not).   Being  in assembler, you  must initialize  the
  3721.      return parameters to avoid string space corrupt errors:
  3722.          Drv$ - minimum 1 for drive character storage
  3723.          Path$ - Up to 64 characters
  3724.          fil$  - up to 12 characters
  3725.          ext$ - 3 characters
  3726.          If the actual size in raw$ exceeds the amount you pass, as much as
  3727.      will fit  will be  returned, and  an error  code will  be returned  to
  3728.      indicate you passed a short string: ext$  = -1, fil$ = -2, path$ = -3,
  3729.      drv$ = -4.  Additionally, if raw$ is NULL, -5 is returned.
  3730.  
  3731.  
  3732.  
  3733.  
  3734.              Name: PCase                    Type: FUNCTION
  3735.          Syntax: p$ = PCase$(p$)
  3736.          PCase can also be invoked with the longer name ProperCase.
  3737.  
  3738.          Converts a passed  test string to  'proper case'.   That is,  "bob
  3739.      smith" is returned as "Bob Smith".  Prior to calling PCASE convert the
  3740.      string to lower case:
  3741.          x$ = "TIMOTHY FOOBAR"
  3742.          x$ = LCASE$(x$)
  3743.          CALL PCase(x$)
  3744.  
  3745.  
  3746.  
  3747.              Name: PGetCh$                   Type: FUNCTION
  3748.          Syntax: ret$ = PGetCH$(prompt$, row, attr, okay$)
  3749.  
  3750.             This routine is  similar to  GETCH in that  it allows  keyboard
  3751.      input only from  a predefined string,  is ANSI compatible and  network
  3752.      functional, but additionally  allows the addition of  an automatically
  3753.      centered prompt.  By  predefining a number of prompts and input masks,
  3754.      a variety of easy to use prompt-and-allowable-input-masks can be setup
  3755.      for  very easy use.   See also  GETCH, DialogBox.   Example: Display a
  3756.      prompt on line 24, in yellow on red, allowing only "YNA" input:
  3757.          prompt$ = "Are You Sure Y/N/Abort"
  3758.          okay$ = "YNA": ky$ = " "
  3759.          CALL pgetch(prompt$, 24, 78, okay$, ky$)
  3760.  
  3761.                    Copyright (C) InfoSoft, 1986-1990, 1991               57
  3762.  
  3763.  
  3764.  
  3765.  
  3766.  
  3767.  
  3768.  
  3769.  
  3770.              Name: PhDrvSet                 Type: SUB
  3771.                    PhDrvClr                 Type: SUB
  3772.                    PhDrvStat                Type: FUNCTION
  3773.          Syntax:  CALL PhDrvSet
  3774.                   CALL PhDrvClr
  3775.                   flag = PhDrvStat
  3776.  
  3777.          Since DOS uses  Drive A: as both  A: and B: on  single floppy sys-
  3778.      tems, it uses  a flag to keep track of what  state it is in.  PhDrvClr
  3779.      and  PhDrvSet allow you to  manipulate this flag  to avoid the "Insert
  3780.      disk in drive  B:..." message in  operations where you  wish to use  a
  3781.      single floppy as  both A: and B:.  PhDrvSet sets  the flag to indicate
  3782.      that drive A: is acting as B:, PhDrvClr clears it to A: acting as  A:.
  3783.       PhDrvStat  returns the  current  status of  the flag  0 (clear)  or 1
  3784.      (set).  Note that should supply your own message and keypress  routine
  3785.      to allow the end user time to swap disks, but certainly, you  can do a
  3786.      better job  than DOS.   Also,  you should  reset the  flag when  done.
  3787.      Example:
  3788.          ..
  3789.          CopyToB:
  3790.              CALL PhDrvSet                      ' Set A: to B:
  3791.              IF DrvError("B") THEN
  3792.                   GOSUB DrvNotReady             ' test it
  3793.              END IF
  3794.              GOSUB CopyBlock                    ' perform operation
  3795.              CALL PhDrvClr                      ' clear flag (A: = A:)
  3796.          RETURN
  3797.  
  3798.  
  3799.              Name: PrgName                  Type: FUNCTION
  3800.          Syntax: errc = PrgName$
  3801.  
  3802.          When we wrote BCLock  (a program that makes your  compiled program
  3803.      aware of changes to itself either from tampering or virus infections),
  3804.      we needed  a way  to get our  OWN file/path name.    This  function is
  3805.      functionally identical to C's 'argv[0]', returning the full  drive and
  3806.      path name of the program executing.  This can be very useful for those
  3807.      that wish  to store operating parameters in the EXE file itself rather
  3808.      than in  a CFG or INI  file.  (The  questionable theory of this  is to
  3809.      open the EXE file and store a TYPE structure of  parameters at the end
  3810.      of the  EXE.   This is  all fine until  the user  attempts to  run the
  3811.      program outside the current  directory (via path) or they  rename your
  3812.      .EXE file  - then  this nifty  idea  comes crashing  to an  insolvable
  3813.      halt).
  3814.  
  3815.          The return  from PrgName  will contain the  drive/pathname of  the
  3816.      currently executing program.   This return  string can then be  parsed
  3817.      into components if desired.   (See also ArgCnt, ArgVar  and GetCmdStr$
  3818.      et al).   Note:  PrgName will  return different information in  the QB
  3819.      environment than as a .EXE file, because the program running is QB.EXE
  3820.      and NOT your program - yet.  Example:
  3821.          MyName$ = PrgName$               ' returns "C:\DIRNAME\FOOBAR.EXE"
  3822.            PRINT "Program running is: "; MyName$
  3823.  
  3824.  
  3825.  
  3826.  
  3827.                    Copyright (C) InfoSoft, 1986-1990, 1991               58
  3828.  
  3829.  
  3830.  
  3831.  
  3832.  
  3833.  
  3834.              Name: PrtQueStat               Type:  FUNCTION
  3835.          Syntax: RetCode = PrtQueStat
  3836.  
  3837.          Fetches the  status of the DOS print queue.  Note that this is the
  3838.      PRINT.COM  file that comes with DOS  and the function is informing you
  3839.      if PRINT is resident  and therefore other PrtQue functions  are avail-
  3840.      able to you.  Possible returns are:
  3841.          -1 = PRINT.COM is installed and resident
  3842.           1 = PRINT.COM not installed and it is NOT ok to install
  3843.           0 = PRINT.COM not installed, ok to install
  3844.  
  3845.          NB: AT  LEAST QB 4.0  (maybe 4.00(a) and  possibly 4.00(b)) has  a
  3846.      problem getting along with PRINT.COM.  Our testing with PRINT.COM from
  3847.      DOS  3.1 and  QB 4.00(b),  BASCOM 6.0 and  QB 4.5  has resulted  in no
  3848.      problems but this is no guaranty of your results.
  3849.  
  3850.  
  3851.              Name: PrtQueSubmit             Type: FUNCTION
  3852.          Syntax: errc = PrtQueSubmit(fil$)
  3853.  
  3854.          Submits a file to the DOS print spooler.  The file must exist, and
  3855.      occasionally it has  seemed that we  needed to pass a  fully qualified
  3856.      drive/path name  before PRINT.COM  would accept  it (see  ExpandPath),
  3857.      however the name may not include wildcards (? or *).  Any return other
  3858.      than 0 indicates an error:
  3859.          0 = File accepted into PrtQue
  3860.          1 = Error accepting file
  3861.  
  3862.  
  3863.  
  3864.  
  3865.              Name: PrtQueDelete             Type: FUNCTION
  3866.          Syntax: errc = PrtQueDelete(fil$)
  3867.  
  3868.          Deletes the  specified filename from the Printqueue, the file must
  3869.      have been previously submitted via  PrtquSubmit, and while it responds
  3870.      to wildcards, a  fully qualified drive/pathname  may be required  (see
  3871.      ExpandPath).  Note  that if the file you wish to delete or remove from
  3872.      the Print Queue is currently being printed, that printing may not halt
  3873.      immediately due  to any  buffering done  by the printer.   Any  return
  3874.      other than 0 indicates an error.
  3875.  
  3876.  
  3877.  
  3878.              Name: PrtQueCancel             Type: FUNCTION
  3879.          Syntax: errc = PrtQueCanel
  3880.  
  3881.          Cancels ALL files currently  in the print queue (these  would have
  3882.      been submitted via PrtQueSubmit).   Note that in cancelling  all files
  3883.      queued, that  PRINT.COM prints  a message  on the  printer noting  the
  3884.      cancellation.  This is DOS or PRINT.COM's doing, not mine.  Any return
  3885.      other than zero  indicates an error.
  3886.  
  3887.  
  3888.  
  3889.  
  3890.  
  3891.  
  3892.  
  3893.                    Copyright (C) InfoSoft, 1986-1990, 1991               59
  3894.  
  3895.  
  3896.  
  3897.  
  3898.  
  3899.  
  3900.              Name: PrtScrn                  Type: SUB
  3901.          Syntax: CALL PrtScrn
  3902.  
  3903.          This very simply sends the current display to the printer.
  3904.  
  3905.  
  3906.  
  3907.              Name: PrtScEnable              Type: SUB
  3908.                    PrtScDisable             Type: SUB
  3909.          Syntax: CALL PrtScDisable
  3910.  
  3911.          These  2 routines  act  to toggle  the  ability of  the  system to
  3912.      perform a Print Screen function.  This can be handy in cases where the
  3913.      information on screen is sensitive to the extent that your application
  3914.      needs to  prevent it from being printed.   Note that TSR type dump-to-
  3915.      disk utilities will  still work, but  once installed Shift-PrtSc  will
  3916.      not work until the system is re-booted or PrtScEnable is called.
  3917.  
  3918.  
  3919.              Name: PtrInit                    Type: SUB
  3920.          Syntax: CALL PtrInit(prtnum)
  3921.  
  3922.          Initialize  the  printer, and  if  the  offline button  is  set to
  3923.      OFFLINE,  it will  put it  online  (most Epsons  anyway)  and set  the
  3924.      printer to TOF  (Top Of Form).   Call it  with the designated  printer
  3925.      port to initialize (1 to 3).  See also PtrStat.  Example:
  3926.          CALL PtrInit(PrinterNum)
  3927.  
  3928.  
  3929.  
  3930.  
  3931.              Name: PtrStat                  Type: FUNCTION
  3932.          Syntax: status = PtrStat(PtrNum)
  3933.  
  3934.            Where PtrInit intializes the printer, PtrStat returns the status
  3935.      of a designated printer  in the form of  0, -1 so you can evaluate the
  3936.      printer status prior to a print function.
  3937.          Pass PtrStat  the printer number  to test (1-3) as  a variable and
  3938.      the variable will be returned as 0 or -1 indicating the status.
  3939.  
  3940.          NOTE:  When testing the  status immediately after calling PtrInit,
  3941.      allow 1 or  2 seconds before calling  PSTAT, this is to  avoid polling
  3942.      the  printer  while it  is still  initializing.   PtrStat  will always
  3943.      indicate the printer online if a spooler is installed.   Example:
  3944.          prtnum=1              ' printer to access
  3945.          CALL PtrInit(prtnum)
  3946.          CALL dly(2)           ' wait for the low tech item to finish
  3947.          stat = PtrStat(prtnum)
  3948.          IF stat THEN
  3949.             ...perform print job ...
  3950.          END IF
  3951.  
  3952.  
  3953.  
  3954.  
  3955.  
  3956.  
  3957.  
  3958.  
  3959.                    Copyright (C) InfoSoft, 1986-1990, 1991               60
  3960.  
  3961.  
  3962.  
  3963.  
  3964.  
  3965.  
  3966.              Name: QCalc&                   Type: FUNCTION
  3967.          Syntax: Result& = QCalc&(TRow, LCol, BodyAttr, ScrnAttr,_
  3968.                    SpeedFactor)
  3969.  
  3970.          (QCalc is fully documented in MACRO17.DOC).  TRow and  LCol is the
  3971.      Top, Left corner  of the calculator, Body and  Scrn are the attributes
  3972.      for the calculator body  and screen and SpeedFactor controls  the type
  3973.      ahead, display and beep speed.
  3974.  
  3975.  
  3976.  
  3977.              Name: QBLoaded                 Type: FUNCTION
  3978.          Syntax: Result = QBLoaded
  3979.          QBLoaded may also be declared and invoked as QBL.
  3980.  
  3981.          This simply checks  to see if  the currently executing program  is
  3982.      QB.EXE.  The use for this is esoteric (although users of an old QB LIB
  3983.      collection that  works differently  in EXE  form as in  the QB  Editor
  3984.      should LOVE  this one!)  but allows  you to  determine of the  process
  3985.      executing in memory  is an .EXE or  a program image being  executed by
  3986.      QB.EXE.  Possible returns are:
  3987.           0   QB Not loaded - EXE file executing
  3988.           1   QB.EXE loaded
  3989.  
  3990.  
  3991.  
  3992.  
  3993.              Name: QPrint                   Type: SUB
  3994.          Syntax: CALL QPrint(text$, row, col, attr)
  3995.  
  3996.          This is a replacement  for BASIC's native PRINT statement.   While
  3997.      QB4 and later are much quicker than earlier  versions, QPrint is still
  3998.      a bit quicker and allows for other features.  Parameters:
  3999.         text$ - String to print
  4000.         row - Row of screen to print text to.
  4001.         col - Column of screen to print to
  4002.         attr - color attributes to use for the text.  This is calculated in
  4003.                the same manner as the attribute  is for Windows, ErrMsg etc
  4004.  
  4005.          Example:
  4006.          msg$="QPRINT is very, very FAST !!"
  4007.          CALL QuikPrt(msg$, 2, 2, MakeAttr(14,4))
  4008.          or directly,
  4009.          CALL QPRINT("QUIKPRT is very, very FAST !!", 2, 2, 78)
  4010.  
  4011.          Note  the  nested Function:  MakeAttr  nested within  the  CALL to
  4012.      QPRINT:  BASIC  will execute  MakeAttr first  and  pass the  RETURN to
  4013.      QPRINT  - however if you are going to use and reuse the attribute, you
  4014.      should assign it to a variable.
  4015.  
  4016.  
  4017.  
  4018.              Name: RamFree                  Type: FUNCTION
  4019.          Syntax: ram = RamFree
  4020.  
  4021.          Returns the amount of memory installed in the machine.
  4022.  
  4023.  
  4024.  
  4025.                    Copyright (C) InfoSoft, 1986-1990, 1991               61
  4026.  
  4027.  
  4028.  
  4029.  
  4030.  
  4031.  
  4032.  
  4033.              Name: ReadScrn                 Type: SUB
  4034.          Syntax: CALL ReadScrn(text$)
  4035.  
  4036.             This  is like BASIC's SCREEN function  except that it is a much
  4037.      faster (on an  order of magnitude) way  to read text from  the screen.
  4038.      ReadScrn uses the  current cursor location  as the starting point  and
  4039.      reads as  many  characters  as you have  spaces in the  passed string.
  4040.      This is critical, since  ASM routines cannot alter string  lengths, if
  4041.      you  want  13 characters,  text$  must be  initialized  to SPACE$(13).
  4042.      Example:
  4043.             ScrnText$=SPACE$(15)
  4044.             LOCATE 12, 15
  4045.             CALL ReadScrn(scrntext$)
  4046.  
  4047.              Name: RepAttr                Type: SUB
  4048.          Syntax: CALL RepAttr(OldAttr, NewAttr)
  4049.  
  4050.          Selectively replaces attributes on the video  display.  All occur-
  4051.      rences of OldAttr are replaced by NewAttr.
  4052.  
  4053.  
  4054.  
  4055.              Name: ReverseString            Type: SUB
  4056.          Syntax: CALL ReverseString(s$)
  4057.          May also be invoked with the shorter name RevStr
  4058.  
  4059.          Reverses all characters in  a string very  quickly.  When used  in
  4060.      conjunction with XLATE, that can be a fairly good encryption system.
  4061.          Example:
  4062.          x$ = "PassWord"
  4063.          CALL RevStr(x$)             ' returns as "droWssaP"
  4064.  
  4065.  
  4066.  
  4067.              Name: RINSTR                   Type: FUNCTION
  4068.          Syntax: position = RINSTR(test$, ch$)
  4069.  
  4070.             Returns the LAST  occurrence of a character in  a string.  This
  4071.      works conversely to BASIC's INSTR, which returns the first occurrence,
  4072.      and is faster and much more code efficient than a loop to keep testing
  4073.      INSTR until the end of the string is reached.  The  character location
  4074.      however is still returned  from the left.      Note: RINSTR works only
  4075.      on character seeks, not  on sub strings like INSTR does.   That is, in
  4076.      the case of  [j = RINSTR("ABCDEFG","A@B") ], RINSTR will only seek and
  4077.      match on "A", not "A@B".  Multiple passes thru RINSTR, however seeking
  4078.      each successive  character in  a sub  string could  be accomplished.  
  4079.      Example:
  4080.              DECLARE FUNCTION RINSTR%(searched$, seek$)
  4081.              ..
  4082.              test$="123456x890" : char$="x"
  4083.              l = RINSTR(test$, char$)                   ' returns 7
  4084.  
  4085.  
  4086.  
  4087.  
  4088.  
  4089.  
  4090.  
  4091.                    Copyright (C) InfoSoft, 1986-1990, 1991               62
  4092.  
  4093.  
  4094.  
  4095.  
  4096.  
  4097.  
  4098.  
  4099.  
  4100.              Name: RTCDateSet/RTCDateGet    Type: FUNCTION(s)
  4101.          Syntax: errc = RTCDateGet(mo, day, yr)
  4102.                  errc = RTCDateSet(mo, day, yr)
  4103.  
  4104.          When running on an AT/286 system, this  allows you to fetch or set
  4105.      the  date held by  the onboard Real  Time Clock.  While  PC's can have
  4106.      battery maintained times,  they tend  to vary greatly  from system  to
  4107.      system as  to how to  access the data held  within.  For  this reason,
  4108.      this will return an error code if the system is not a 286:
  4109.          -2 = System not an AT/286
  4110.          -1 = Time/Date update in progress (try again)
  4111.  
  4112.          See also RTCTimeGet/RTCTimeSet
  4113.  
  4114.  
  4115.  
  4116.              Name: RTCTimeSet/RTCTimeGet    Type: FUNCTION(s)
  4117.          Syntax: errc = RTCTimeGet(hr, min, sec, hund)
  4118.                  errc = RTCTimeSet(hr, min, sec, hund)
  4119.  
  4120.          AT/286 systems include an onboard battery maintained clock that
  4121.      maintains the time and date when the system is off.  This routine will
  4122.      read or set  the time portion held there.   This can be  handy to make
  4123.      sure that no  one is trying to trick your application by resetting the
  4124.      DOS time (or date), by reading the time (or date) directly  from CMOS.
  4125.      For additional info see RTCDateGet/RTCDateSet.
  4126.  
  4127.  
  4128.              Name: RunCmdL                  Type: SUB
  4129.          Syntax: CALL RunCmdL(cmd$)
  4130.          May also be called with RunCommandLine
  4131.  
  4132.          If you  have ever  used QB's RUN  to execute another  program, you
  4133.      know that it is impossible to change or alter the command line - until
  4134.      now.  As is, QB passes the original PSP (Program Segment Prefix) which
  4135.      contains  the environment  and  the command  tail to  these subsequent
  4136.      processes.  RunCmdL  basically alters COMMAND$ so that  you can pass a
  4137.      new command tail to  a RUN program.  Simply pass  RunCmdL whatever new
  4138.      COMMAND$ you want the RUN program to act on, and that RUN program will
  4139.      have a new COMMAND$.  The maximum  length is 128 characters.  DOS  may
  4140.      overwrite the first few characters  of cmd$ with the filename to  RUN,
  4141.      so be sure to  pre pad it with enough spaces to compensate.  To cancel
  4142.      a Command  Tail, simply pass  a single space  more than that  filename
  4143.      length.    Example:
  4144.      cmd$ = "       /C /1 foobar.dat COLOR"    ' note leading spaces
  4145.      CALL RunCmdL(c$)
  4146.      RUN "Foobar"
  4147.  
  4148.          Note the leading  spaces enough  to allow FOOBAR  to be  overlayed
  4149.      plus one space as a separator.  RunCmdL works in the QB environment as
  4150.      well as  a EXE.
  4151.  
  4152.  
  4153.  
  4154.  
  4155.  
  4156.  
  4157.                    Copyright (C) InfoSoft, 1986-1990, 1991               63
  4158.  
  4159.  
  4160.  
  4161.  
  4162.  
  4163.  
  4164.  
  4165.              Name: SaveScrn/RestScrn        Type: SUB
  4166.          Syntax: CALL SaveScrn(SEG arry(x))
  4167.                  CALL RestScrn(SEG arry(x))
  4168.  
  4169.            The SaveScrn  routine  saves the  current screen  display to  an
  4170.      integer array then via RestScrn  you can restore that saved  screen to
  4171.      the display.  This is very handy in a  routine in situations where you
  4172.      might want to pop  a help window to the  display.  You could save  the
  4173.      current screen, display  a help  window or screen,  then upon  command
  4174.      redisplay  the  original screen.     The  GLIB implementation  is very
  4175.      undemanding - the  array which we save  to and from can be  DYNAMIC or
  4176.      STATIC, the Save  and Restore screen  functions will work with  either
  4177.      type of array, and both in EXE files and from the QB environment.
  4178.  
  4179.             Additionally, Save/Rest Scrn not only recognizes extended video
  4180.      type (like VGA,  EGA and MCGA), but  video modes other than  80*25 are
  4181.      supported - if  your VGA is in 80  * 43 mode, Save/Rest  Scrn will see
  4182.      that and save 3440 character/attribute pairs rather than 2000 (be sure
  4183.      to allow for 3440 integers rather than 2000 in this case!).  Example:
  4184.  
  4185.  
  4186.          DECLARE SUB SaveScrn(SEG Array%)
  4187.          DECLARE SUB RestScrn(SEG Array)
  4188.          ..
  4189.          ..
  4190.          REDIM ScrnArry(10000)        ' enough for 5 (80 x 25) screens
  4191.  
  4192.          CALL SaveScrn(ScrArry(1))    ' save current screen to pos 1
  4193.          CALL RestScrn(ScrArry(4000)) ' restore from screen pos 3
  4194.  
  4195.  
  4196.       INTEGER variables can be used to point to the screen offsets:
  4197.  
  4198.  
  4199.      Scrn1 = 1 : Scrn2 = 2001             ' simple variable
  4200.      CONST SCRN3 = 4001, SCRN4 = 6001     ' constants work too!
  4201.  
  4202.      CALL SaveScrn(ScrArry(Scrn1))        ' save display to offset 1
  4203.      GOSUB DoHELP
  4204.      CALL RestScrn(ScrArry(SCRN4))        ' restore from offset 6001
  4205.  
  4206.  
  4207.          For more information,  examine the  demo source code,  as these  2
  4208.      routines  are used quite  a bit.   In the demo,  a deliberate delay is
  4209.      used in some cases  to slow down the save and restore process to allow
  4210.      you time to perceive some processes.
  4211.  
  4212.  
  4213.  
  4214.  
  4215.  
  4216.  
  4217.  
  4218.  
  4219.  
  4220.  
  4221.  
  4222.  
  4223.                    Copyright (C) InfoSoft, 1986-1990, 1991               64
  4224.  
  4225.  
  4226.  
  4227.  
  4228.  
  4229.  
  4230.  
  4231.              Name: SaveWindow               Type: SUB
  4232.                    RestWindow
  4233.          Syntax: CALL SaveWindow(SEG arry(x), TR, LC, BR, LC)
  4234.                  CALL RestWindow(SEG arry(x), TR, LC, BR, LC)
  4235.          These may be invoked with the shorter names SvWdw and RstWdw
  4236.  
  4237.  
  4238.          Where SaveScrn  and RestScrn  save and  restore the  entire screen
  4239.      (taking 4000 bytes  of memory to  do so), Save  / RestWindow save  and
  4240.      restore only a portion of the screen as might be needed  to manage the
  4241.      section  of the  screen that  will be altered  from a  window display.
  4242.      Since the size of  the array required varies depending on  the size of
  4243.      the window, use BuffCalc to calculate the precise size needed.  
  4244.  
  4245.       Example:
  4246.  
  4247.          DECLARE SUB SaveWindow(SEG arry, TR, LC, BR, RC)
  4248.          DECLARE SUB RestWindow(SEG arry, TR, LC, BR, RC)
  4249.          .. 
  4250.          ..
  4251.          ..
  4252.          CASE 17                     ' Help function
  4253.              size = BuffCalc(1, 40, 20, 80)
  4254.              REDIM HelpWdw(size)                     ' get array size
  4255.              CALL SaveWindow(HelpWdw(1), 1, 40, 20, 80)  
  4256.                     ' save screen under wdw
  4257.  
  4258.              CALL HELP                                   ' do help
  4259.              CALL RestWindow(HelpWdw(1), 1, 40, 20, 80)
  4260.          ..
  4261.          ..
  4262.      See SvScrn / RstScrn for general info on screen save techniques.
  4263.  
  4264.  
  4265.  
  4266.  
  4267.  
  4268.              Name: ScrlOn / ScrlOff         Type: SUB
  4269.          Syntax: CALL ScrlOn
  4270.  
  4271.          Toggles the  scroll lock key  on or off.   If the keyboard  is eq-
  4272.      uipped with LED's, they are also toggled to the appropriate state.
  4273.  
  4274.  
  4275.  
  4276.  
  4277.  
  4278.  
  4279.  
  4280.  
  4281.  
  4282.  
  4283.  
  4284.  
  4285.  
  4286.  
  4287.  
  4288.  
  4289.                    Copyright (C) InfoSoft, 1986-1990, 1991               65
  4290.  
  4291.  
  4292.  
  4293.  
  4294.  
  4295.  
  4296.              
  4297.              Name: ScrnDump                 Type: FUNCTION
  4298.          Syntax: errc = ScrnDump(fhandle)
  4299.  
  4300.          Very simply, this  reads thru video memory,  removes the attribute
  4301.      byte  and dumps  the text  to  disk, adding  a CR/LF  pair  every 80th
  4302.      character except on the last line.  This is very fast and works with a
  4303.      DOS file  handle -  either open  the file  with FOPEN  or use  BASIC's
  4304.      FILEATTR to  ascertain the  handle from a  BASIC fileno.   If  you use
  4305.      BASIC's  "OPEN ...   FOR", ScrnDump will  respect the  mode (OUTPUT or
  4306.      APPEND) and it  would be VERY  unlikely that any error  occurs because
  4307.      the legitimacy of  the file name would  have been check by  BASIC when
  4308.      OPENed.
  4309.  
  4310.      ScrnDump will return errc  as 6 if the handle is not  valid - the only
  4311.      likely error short of a disk error.  Example:
  4312.          ff = FREEFILE                            ' get handle
  4313.          OPEN "scrndump.fil" FOR APPEND AS #ff    ' open file
  4314.          fh = FILEATTR(ff,2)                      ' fileno => fhandle
  4315.          errc = ScrnDump(fh)
  4316.  
  4317.  
  4318.  
  4319.              Name: ScrnDumpB                Type: FUNCTION
  4320.          Syntax: errc = ScrnDumpB(fhandle)
  4321.  
  4322.          This  works very  similar  to ScrnDump,  except  that rather  than
  4323.      dumping a text file, it leaves video memory in binary format.  This is
  4324.      similar to the BSAVE function in BASIC except that the signature bytes
  4325.      are omitted  and you can APPEND the screen  image to an existing file.
  4326.      In so doing,  you can basically  make a binary  screen library.   Add-
  4327.      itionally some  periodic  bugs in  BSAVE with  DOS 2.0  and/or QB  are
  4328.      avoided.
  4329.          Example:
  4330.          ff = FREEFILE                            ' get handle
  4331.          OPEN "scrndump.fil" FOR APPEND AS #ff    ' open file
  4332.          fh = FILEATTR(ff,2)                      ' fileno => fhandle
  4333.          errc = ScrnDumpB(fh)
  4334.  
  4335.  
  4336.  
  4337.              Name: ScrnWash                 Type: SUB
  4338.          Syntax: CALL ScrnWash
  4339.          ScrnWash may also be called as MonoScrn
  4340.  
  4341.          ScrnWash removes the  color from  the screen display  in order  to
  4342.      make it  suitable  for  a  Monochrome or  Composite  system.  ScrnWash
  4343.      converts colors 1 to  6 to 7 (white) and converts colors 9 to 14 to 15
  4344.      (hi int white).   In effect, it washes the colors  out to black, white
  4345.      and hi intensity white.
  4346.  
  4347.  
  4348.  
  4349.  
  4350.  
  4351.  
  4352.  
  4353.  
  4354.  
  4355.                    Copyright (C) InfoSoft, 1986-1990, 1991               66
  4356.  
  4357.  
  4358.  
  4359.  
  4360.  
  4361.  
  4362.  
  4363.              Name: ScrollL/ScrollR          Type: SUB
  4364.          Syntax: CALL ScrollL(Tr, Lc, Br, Rc, FillAttr, NumLines)
  4365.          Syntax: CALL ScrollR(Tr, Lc, Br, Rc, FillAttr, NumLines)
  4366.          These may also be called as ScrlLeft and ScrlRght
  4367.  
  4368.             This routine  scrolls the entire screen or a portion of it left
  4369.      or right  the designated  number of  lines.   The scrolled or  blanked
  4370.      portion of  the screen is filled  in with the designated  attribute if
  4371.      the attribute value is 0  to 128.  If the attribute value  is -1, then
  4372.      the attribute is left unchanged.  Example:
  4373.      CALL ScrlLeft(1, 1, 25, 80, -1, 4)   ' scroll screen left 4 cols
  4374.      CALL ScrlRight(5, 5, 18, 60, 7, 15)  '  scroll a window right 15 cols 
  4375.                                   
  4376.  
  4377.  
  4378.              Name: ScrollUp / ScrollDn      Type: SUB
  4379.          Syntax: CALL ScrollUp(TRow, LCol, BRow, RCol, attr, Num)
  4380.                  CALL ScrollDn(TRow, LCol, BRow, RCol, attr, Num)
  4381.  
  4382.          These 2 routines scroll a portion (or all)  of the current display
  4383.      up or down a  user defined number of times.  SCROLL  allows for you to
  4384.      set the  parameters for  all four  boundaries: top,  bottom, left  and
  4385.      right.  Additionally,  you designate  the number of  lines to  scroll.
  4386.      Designating 0  as the number  of lines  to scroll, clears  the screen.
  4387.      Parameters:
  4388.          Top, left,  bottom and right, relate to the  bounds of the area to
  4389.      scroll, attribute  is the  color to  use to  fill the  portion of  the
  4390.      screen affected, and Num is the number of lines to scroll.  Example:
  4391.  
  4392.          num=12 : top=1 : lft=1 : bttm=12 : rght=79
  4393.          CALL ScrollDn(top, lft, bttm, rght, 112, num)
  4394.              ' scrolls lines 1 to 12 down 12 lines - lines  13 to 25       
  4395.              '   are lost
  4396.  
  4397.          CALL ScrollUp(13, 1, 25, 79, 7, 12)
  4398.              ' scrolls lines 12 to 25 up 12 lines -  with 13-25         
  4399.              '   becoming blank.
  4400.  
  4401.          CALL ScrollD(1, 1, 25, 79, 7, 25)
  4402.              ' Clears the screen with the display scrolling down off       
  4403.              '   the screen
  4404.  
  4405.  
  4406.  
  4407.              Name: SetDrv                   Type: SUB
  4408.          Syntax: CALL SetDrv(drv$)
  4409.  
  4410.          Sets or resets the  default drive.  To set the  drive, simply pass
  4411.      it the letter,  upper or lower  case, to log  into.  This removes  the
  4412.      ambiguity of drive numbers (Hmm, is drive 1 A: or B: in this case...).
  4413.      SetDrv  returns  nothing and  if passed  a  bad parameter,  DOS simply
  4414.      rejects it leaving the default drive unchanged.  Example:
  4415.          drv$="d"
  4416.          CALL setdrv(drv$)
  4417.  
  4418.  
  4419.  
  4420.  
  4421.                    Copyright (C) InfoSoft, 1986-1990, 1991               67
  4422.  
  4423.  
  4424.  
  4425.  
  4426.  
  4427.  
  4428.  
  4429.              Name: SetErrLvl                Type: SUB
  4430.          Syntax: CALL SetErrLvl(ERRORLEVEL)
  4431.  
  4432.             Sets return code upon  program termination.  These can  be read
  4433.      from DOS via as "ERRORLEVELs" in batch files.  This routine  should be
  4434.      called near the end of a program.  It WILL NOT terminate your program,
  4435.      upon  execution, but will merely change the  QB RTL (Run Time Library)
  4436.      default return code  ("ERRORLEVEL") so that  when the program is  ter-
  4437.      minated with END or SYSTEM, your redefined error level is used.
  4438.  
  4439.          Since  this is an interrupt  service routine, ie  we take over the
  4440.      DOS interrupt function to terminate, it  MUST NOT be called more  than
  4441.      once in a program.  Further, since there is no way to uninstall it, it
  4442.      should not be  called from  inside the  environment -  you should  not
  4443.      revector  interrupts  without installing  them  before dropping  to QB
  4444.      editor level. (This goes  for NoBoot, Clock  and DrvErr too, but  they
  4445.      can be uninstalled!).
  4446.          Example 1:
  4447.          CALL SetErrLvl(code)            ' terminate and set "ERRORLEVEL"
  4448.  
  4449.          Example 2:
  4450.          IF ErrCode THEN
  4451.              PRINT "ABEND"
  4452.              CALL SetErrLvl(ErrCode)
  4453.          ELSE
  4454.              PRINT "Normal Termination"
  4455.              SYSTEM
  4456.          END IF
  4457.  
  4458.  
  4459.  
  4460.  
  4461.              Name: ShareInst                Type: FUNCTION
  4462.          Syntax: RetCode = ShareInst
  4463.  
  4464.          Returns a  non zero  value if  SHARE is  installed.   This can  be
  4465.      helpful  at the  start of a  program in  determining the type  of file
  4466.      access to use.
  4467.          Example:
  4468.      IF ShareInst = 0 THEN
  4469.          PRINT "Sorry, this version requires SHARE.EXE be installed!" 
  4470.      END IF
  4471.  
  4472.  
  4473.  
  4474.              Name: ShiftLeftI/ShiftRightI   Type: FUNCTION
  4475.          Syntax: Result = ShiftLeftI(value, ShiftCount)
  4476.                  Result = ShiftRightI(value, ShiftCount)
  4477.          These  can also  be called  by the  similar assembler  instruction
  4478.      names ShlI and ShrI.
  4479.  
  4480.          This returns RESULT after the integer  VALUE has been shifted left
  4481.      or right the number of times indicated in ShiftCount.  Besides provid-
  4482.      ing a quick  multiplication and division  method, it is handy  for bit
  4483.      operations  such as  isolating the date  bits in  a DATE word  for in-
  4484.      stance.
  4485.  
  4486.  
  4487.                    Copyright (C) InfoSoft, 1986-1990, 1991               68
  4488.  
  4489.  
  4490.  
  4491.  
  4492.  
  4493.  
  4494.  
  4495.              Name: ShutDown                 Type: SUB
  4496.          Syntax: CALL ShutDown(graphics)
  4497.  
  4498.          This parks  any fixed disks  in the system, shuts  down the system
  4499.      and via if the graphics switch is set (non zero), a graphic display of
  4500.      the Big  Red Switch  is drawn  center screen.   HALT  provides a  more
  4501.      economical version of ShutDown by skipping the parking and picture.
  4502.  
  4503.  
  4504.  
  4505.              Name: Sleeper                  Type: SUB
  4506.          Syntax: CALL Sleeper(x)
  4507.  
  4508.          This  works identically to  BASIC's intrinsic  SLEEP by  waiting x
  4509.      secs for a keypress or,  if x is set to zero it will  wait forever for
  4510.      that keypress.   Using SLEEP implicitly sets  up an EVENT trap.   That
  4511.      is, if  you link  your program  with the NOEVENT.OBJ  stub file,  some
  4512.      versions of the compiler will cause your  program will lock up or bomb
  4513.      out when  it reaches the  SLEEP statement  because it needs  the EVENT
  4514.      code that you stubbed out.  Sleeper allows you  to still link with NO-
  4515.      EVENT.OBJ and/or produce smaller  code size by omitting all  the event
  4516.      trapping code.
  4517.  
  4518.  
  4519.  
  4520.              Name: SpkrOn/SpkrOff           Type: SUB
  4521.          Syntax: Call SpkrOn
  4522.                  Call SpkrOff
  4523.          SpkrOn may also be called as SpeakerOn and SpkrOff as SpeakerOff
  4524.  
  4525.          These enable or disable the PC speaker.   With the speaker toggled
  4526.      off,  BASIC's  SOUND statements  will execute,  but  no sound  will be
  4527.      emitted.  Allowing  for total program  configuration, if the end  user
  4528.      does not want sound, you can kill the speaker with one line of code:
  4529.  
  4530.          CALL SpkrOff
  4531.  
  4532.          rather then the following in hundreds of places in your code:
  4533.  
  4534.          IF SoundFXON THEN
  4535.             FOR x = 1 TO 8
  4536.                 SOUND f, d
  4537.             NEXT x
  4538.          END IF
  4539.          Note  that  good  programming  practices  would dictate  that  you
  4540.      restore the speaker state (SpkrOn) before your program terminates.
  4541.  
  4542.  
  4543.  
  4544.              Name: SpkrSnd                  Type: SUB
  4545.          Syntax: Call SpkrSnd(BYVAL freq, BYVAL dur)
  4546.          SpkrSnd may also be called as SpeakerSnd
  4547.  
  4548.          Emits a tome on the PC speaker  of the specified frequency for the
  4549.      number  of clock ticks specified  by duration.   The advantage to this
  4550.      over SOUND is that this adds less overhead and is slightly faster.
  4551.          Example:   CALL SpkrSnd(750, 5)    ' Equivalent to BEEP
  4552.  
  4553.                    Copyright (C) InfoSoft, 1986-1990, 1991               69
  4554.  
  4555.  
  4556.  
  4557.  
  4558.  
  4559.  
  4560.  
  4561.  
  4562.           Name: Soundex/SoundexM            Type: FUNCTION
  4563.          Syntax: code$ = Soundex(text$)
  4564.  
  4565.          The Soundex process is a  fabulous algorithm developed by  Michael
  4566.      Baldwin  of AT&T  Labs.  Soundex  allows you to  convert English text,
  4567.      words  or names to a fundamental code  so that 'botl', 'bottel', 'btl'
  4568.      and 'bottle' (and several more misspellings and botched abbreviations)
  4569.      would all look alike to your code.  In searching a large databases for
  4570.      a name,  when using Soundex,  the end user  really only needs  to know
  4571.      'sort of' how it SOUNDS (not spelled)!
  4572.  
  4573.          To clarify what  Soundex does, note  that both CATSUP and  KETCHUP
  4574.      return a similar Soundex code.   This Soundex code is expressed as a 4
  4575.      character code in the form '?nnn' where '?' is the first letter of the
  4576.      word/name, and each  'n' is the balance  of the encoded word  or name.
  4577.      If the  encoding does  not take  up all  3 characters  the balance  is
  4578.      filled with zeroes (eg: L300).
  4579.  
  4580.          One drawback is that names  or words with foreign origins may  not
  4581.      come back with  logical Soundex codes:  'lummox' (a lazy oaf)  returns
  4582.      the same code  as 'Lemieux'.  Now,  Mr. Lemieux may indeed  be an oaf,
  4583.      but the words do not sound at all alike.
  4584.  
  4585.          SoundexM is a modification to the Soundex routine that follows the
  4586.      conventional  algorithm, but rather than being  in "?nnn" format, it  
  4587.      encodes the first  character too.  The  advantage of this is  that the
  4588.      code  can then be made  part of a  file record and it  takes up only 2
  4589.      bytes (INTEGER).   Additionally, when searching large  databases, with
  4590.      the  first letter  coded or  quantified, record  search  and retrieval
  4591.      using binary searches  and other fast  hashing techniques can be  used
  4592.      with great effect. 
  4593.  
  4594.          Examples:
  4595.  
  4596.          Word            Soundex      SoundexM
  4597.          -----           -------      --------
  4598.          Catsup           C321          2321
  4599.          Ketchup          K321          2321
  4600.          Lemieux          L520          4520
  4601.          Ohlemeyer        O456          0456
  4602.          AirReturnFan     A636          0636
  4603.          LLoyd            L300          4300    **
  4604.          Ladd             L300          4300    **
  4605.          ( ** many Soundex algorithms fail on these)
  4606.  
  4607.  
  4608.          I tend to use a combination of  both Soundex and SoundexM: I store
  4609.      the Soundex code in files for fast compares, but also use LEFT$(x$, 1)
  4610.      or the first letter for alphabetical reference.
  4611.  
  4612.  
  4613.  
  4614.  
  4615.  
  4616.  
  4617.  
  4618.  
  4619.                    Copyright (C) InfoSoft, 1986-1990, 1991               70
  4620.  
  4621.  
  4622.  
  4623.  
  4624.  
  4625.  
  4626.  
  4627.              Name: StatLine                 Type: FUNCTIONs
  4628.          (PrintStatL, CLX and SetBVLine are thoroughly covered in          
  4629.           MACROxx.DOC).
  4630.  
  4631.  
  4632.  
  4633.          
  4634.              Name: StrLenMax/StrLeMin       Type: FUNCTION(s)
  4635.          Syntax: Min = StrLenMax(BYVAL(VARPTR(Array$(x))), Quan)
  4636.               Max = StrLenMax(BYVAL(VARPTR(Array$(x))), Quan)
  4637.  
  4638.          Passed a string array, these will scan the array up to Quan number
  4639.      of elements (the  whole array or just  a portion), to find  either the
  4640.      longest or shortest string length. This  is  much   faster  and   more
  4641.      compact  than fashioning  loops  in BASIC.   Take  care that  the Quan
  4642.      parameter  will not tell  StrLen--- to scan  beyond the limits  of the
  4643.      array or invalid results will be returned.
  4644.  
  4645.          DECLARE FUNCTION StrLenMax(BYVAL ptr%, Quan%)
  4646.          ..
  4647.          ..
  4648.          REDIM Array$(125)
  4649.          ..
  4650.          ' this will scan elements 10 to 30 to find the longest string.
  4651.          MaxL = StrLenMax(VARPTR(Array$(10)), 20)
  4652.  
  4653.          ' this will scan the entire array to find the shortest string
  4654.          MinL = StrLenMin(VARPTR(Array$(1)), UBOUND(Array$))
  4655.          ' same thing
  4656.          MinL = StrLenMin(VARPTR(Array$(1)), 125)
  4657.  
  4658.  
  4659.  
  4660.  
  4661.  
  4662.  
  4663.  
  4664.  
  4665.  
  4666.  
  4667.  
  4668.  
  4669.  
  4670.  
  4671.  
  4672.  
  4673.  
  4674.  
  4675.            
  4676.  
  4677.  
  4678.  
  4679.  
  4680.  
  4681.  
  4682.        
  4683.  
  4684.  
  4685.                    Copyright (C) InfoSoft, 1986-1990, 1991               71
  4686.  
  4687.  
  4688.  
  4689.  
  4690.  
  4691.  
  4692.              Name: SubDirCount              Type: FUNCTION
  4693.          Syntax: count = SubDirCount(mask$)
  4694.  
  4695.          Count the number  of subdirectories matching  a given mask.   This
  4696.      counts the number of files with the directory attribute in the default
  4697.      directory.   Note that  while it is  unusual, a directory  CAN have an
  4698.      extension.    Example:   
  4699.           DirCnt = SubDirCount("*.*")
  4700.  
  4701.  
  4702.              Name: SubDirCH                 Type: FUNCTION
  4703.              Name: SubDirMK                 Type: FUNCTION
  4704.              Name: SubDirRM                 Type: FUNCTION
  4705.          Syntax: errc = SubDirCH(SubDirName$)
  4706.                  errc = SubDirMK(SubDirName$)
  4707.                  errc = SubDirRM(SubDirName$)
  4708.  
  4709.          Changes (SubDirCH), Makes (SubDirMK) or Removes (SubDirRM) the sub
  4710.      directory specified by  SubDir$.   The advantage  over BASIC's  native
  4711.      CHDIR  is that  if  any error  is encountered,  rather  than an  error
  4712.      condition  being forced on  your code, an error  code is returned. The
  4713.      return code is set (non zero) if an error is encountered.
  4714.  
  4715.  
  4716.  
  4717.  
  4718.              Name: SubDirExist              Type: FUNCTION
  4719.          Syntax: RetCode = SubDirExist(mask$)
  4720.  
  4721.          Returns a non zero value if a given sub directory exists, and zero
  4722.      if it does not.     Example:
  4723.          IF SubDirExists("QB45") THEN
  4724.              CHDIR "QB45"
  4725.          ELSE
  4726.              PRINT "No can do"
  4727.          END IF
  4728.  
  4729.  
  4730.  
  4731.              Name: SubDirGet                Type: FUNCTION
  4732.          Syntax: CurDir$ = SubDirGet$
  4733.  
  4734.          Returns a string representing the current,  default directory.  . 
  4735.  
  4736.       
  4737.  
  4738.              Name: SubDirList               Type: FUNCTION
  4739.          Syntax: ErrCode = SubDirList(mask$, VARPTR(DirNames$(x)))
  4740.  
  4741.          SubDirList works almost identically to the function Dir, except it
  4742.      fetches  filenames that bear  the directory attribute  into the string
  4743.      array.  By passing a mask, it allows  you to optionally get only those
  4744.      names  that your  program  has  created  or  controls;  ie  FooBar.EXE
  4745.      creates, gets and uses  \FBData, \FBPrntr and \FBReports, so  the mask
  4746.      would be \FB*.*.   Also  note that  directories can have  dots in  the
  4747.      name.
  4748.  
  4749.                        
  4750.  
  4751.                    Copyright (C) InfoSoft, 1986-1990, 1991               72
  4752.  
  4753.  
  4754.  
  4755.  
  4756.  
  4757.  
  4758.  
  4759.              Name: SysTicks                 Type: FUNCTION
  4760.          Syntax: TicksSoFar& = SysTicks&
  4761.  
  4762.          SysTicks returns the number of clock ticks that have elapsed since
  4763.      midnight.   This  allows for  an  even finer  resolution of  time that
  4764.      SysTime or TIMER.  Note that SysTicks returns a LONG integer.
  4765.  
  4766.  
  4767.  
  4768.              Name: SysTime                  Type: SUB
  4769.          Syntax: CALL SysTime(hrs, mins, secs, hund)
  4770.  
  4771.             Rather than tearing apart BASIC's  TIME$ with MID$ to determine
  4772.      the current hour, minute, second, SysTime allows instant access to all
  4773.      that PLUS the hundredths of a second with no string garbage generated.
  4774.      Note that earlier clone BIOSes may not return hundredths of a  second,
  4775.      so it may not be accurate on all systems.
  4776.  
  4777.  
  4778.  
  4779.  
  4780.              Name: TFRMAT                   Type: SUB         (BASIC)
  4781.          Syntax: CALL TFrmat(nutime$, mode)
  4782.  
  4783.          TFRMAT  allows  for  Time string  formatting  similar  to  that in
  4784.      DFRMAT.  There  is no error checking that a valid  time is passed, but
  4785.      if the mode parameter is not set right, an error message of: " Invalid
  4786.      mode specified" will be returned in T$, also m will be set to 50.  The
  4787.      parameter  MODE  controls the optional label  -  0 = OFF  / none,  1 =
  4788.      "am" / "pm" whichever is appropriate
  4789.          Example:                                 Output:
  4790.          PRINT TIME$                              13:01:01
  4791.          CALL tfrmat(nutime$,1)
  4792.          PRINT nutime$                             1:01 pm
  4793.  
  4794.  
  4795.  
  4796.              Name: TimerToggle              Type: SUB
  4797.          Syntax: CALL TimerToggle(TimerNum, Toggle)
  4798.  
  4799.          TimerToggle and TimerElapsed provide for an assembler based medium
  4800.      resolution set of timers.  The granularity of  these timers is approx-
  4801.      imately 976 milliseconds.  These Timer----  functions allow for 5 dif-
  4802.      ferent time slots so  that you can track several  different processes.
  4803.      When invoking TimerToggle,  TimerNum should  be 1 to 5 indicating  the
  4804.      timer  to toggle (a  number less than  one or more than  5 should exit
  4805.      doing  nothing.)   The  Toggle  parameter  indicates  whether you  are
  4806.      starting or stopping that timer: 0 HALTS or stops the timer, any other
  4807.      value starts it.  If a  given timer has already been started,  issuing
  4808.      another START command for that timer causes the previous start time to
  4809.      be overwritten  - that  is a  timer cannot  be RE-started.   See  also
  4810.      TimerElapsed&.
  4811.  
  4812.  
  4813.  
  4814.  
  4815.  
  4816.  
  4817.                    Copyright (C) InfoSoft, 1986-1990, 1991               73
  4818.  
  4819.  
  4820.  
  4821.  
  4822.  
  4823.  
  4824.  
  4825.  
  4826.  
  4827.              Name: TimerElapsed&            Type: FUNCTION
  4828.          Syntax: ProcTime& = TimerElapsed&(TimerNum)
  4829.  
  4830.          Fetches the  number of  elapsed  clock ticks  since the  specified
  4831.      timer was started.   If the timer  was never started, garbage  is ret-
  4832.      urned.  TimerNum  refers to an integer  1 to 5 indicating  which timer
  4833.      elapsed time is to be returned.  TimerElapsed& returns a LONG INTEGER,
  4834.      so be sure to use the right data type.  Also TimerElapsed& does not do
  4835.      an implicit timer stop  function, it merely returns the  difference of
  4836.      the start and stop ticks for that timer. 
  4837.  
  4838.       Example:
  4839.  
  4840.          CALL TimerToggle(1,1)            ' start timer one
  4841.          ..
  4842.          CALL TimerToggle(1,0)            ' stop timer one
  4843.          ProcTime& = TimerElapsed&(1)     ' get elapsed timer ticks        
  4844.                                   '   into ProcTime&
  4845.  
  4846.  
  4847.  
  4848.  
  4849.  
  4850.  
  4851.  
  4852.  
  4853.  
  4854.              Name: TimeSquare               Type: FUNCTION     (BASIC)
  4855.          Syntax: KeyPress = TimeSquare(Msg$(), Row, Col, Attr, Cycles)
  4856.  
  4857.          This flashy little number provides a revolving display of messages
  4858.      from  the array  passed simulating  the marquee/reader board  found in
  4859.      Times Square, NYC.  TimeSquare returns after Cycles number of complete
  4860.      displays have been completed or a key is pressed.    Parameters:
  4861.          Msg$()     - The string array of messages to display
  4862.          Row, Col   - Row and column for the message(s) display
  4863.          Attr       - Attribute for the message display
  4864.          Cycles     - Determine the number of complete cycles for the      
  4865.                       collection  of messages.  If set to less than        
  4866.                       one, the complete set of messages is displayed  at   
  4867.                       least one  time before a keypress will interrupt it. 
  4868.                       If  Cycles is negative and no key is ready after the 
  4869.                       first rotation, the display continues until          
  4870.                       ABS(cycles) have been displayed.
  4871.  
  4872.          TimeSquare   requires  QPrint,   KeyReady   and  Delay18.      Use
  4873.      Save/RestWindow  to  restore  the  section   of  screen  disturbed  by
  4874.      TimeSquare.
  4875.  
  4876.  
  4877.  
  4878.  
  4879.  
  4880.  
  4881.  
  4882.  
  4883.                    Copyright (C) InfoSoft, 1986-1990, 1991               74
  4884.  
  4885.  
  4886.  
  4887.  
  4888.  
  4889.  
  4890.  
  4891.              Name: Translate                Type: FUNCTION
  4892.          Syntax: errc = Translate(source$, table$)
  4893.          TRANSLATE can also be called by the name XLATE
  4894.  
  4895.          This will translate or substitute  all characters in SOURCE$  from
  4896.      the list of  characters in TABLE$  based on their  ASCII value.   Note
  4897.      that since this may be  as high as 255,  that TABLE$ should allow  for
  4898.      all possibilities  and be 256 characters  long.  This provides  for an
  4899.      easy and configurable encryption scheme.
  4900.          Example:
  4901.          FOR x = 1 to 256
  4902.              Table$ = Table$ + CHR$(256 - x)
  4903.          NEXT x
  4904.          Serial$ = "123456"
  4905.          errc = Translate(Serial$, Table$)
  4906.          The result is that '1' becomes ASCII 206  because TABLE$ is the   
  4907.          ASCII table backwards.  So '1' is 49 and 255 - 32 = 206.
  4908.  
  4909.                     
  4910.  
  4911.  
  4912.              Name: ValidDrv                 Type: FUNCTION
  4913.          Syntax: result = ValidDrv(drv$)
  4914.  
  4915.          ValidDrv tests a given character passed to see if it is possibly a
  4916.      valid drive character.  The return is 0 or non zero indicating if  the
  4917.      drive  is  valid and  available.    The spectacular  thing  about this
  4918.      function is that it returns LOGICAL, not just physical drives, so that
  4919.      if the  DOS version is greater than 3.0,  if SUBST or networking soft-
  4920.      ware are  in use, ValidDrv will  return correct information -  this is
  4921.      done by accessing the IOCTL functions if DOS 3.0 or greater is active.
  4922.      The only  possible non  true return would  be drive  B: in  which, the
  4923.      system recognizes A: as B: when only one floppy is installed.
  4924.  
  4925.          Example:
  4926.  
  4927.          DECLARE FUNCTION ValidDrv%(a$)
  4928.          ..
  4929.          ..
  4930.          FOR x = 1 TO 26
  4931.              PRINT CHR$(x+64);
  4932.              IF ValidDrv(CHR$(x+64)) THEN
  4933.                  PRINT " is a valid, active drive letter."
  4934.              ELSE
  4935.                  PRINT " is not a valid drive letter."
  4936.              END IF
  4937.          NEXT x
  4938.  
  4939.  
  4940.  
  4941.  
  4942.  
  4943.  
  4944.  
  4945.  
  4946.  
  4947.  
  4948.  
  4949.                    Copyright (C) InfoSoft, 1986-1990, 1991               75
  4950.  
  4951.  
  4952.  
  4953.  
  4954.  
  4955.  
  4956.              Name: VerifyGet                Type: FUNCTION
  4957.          Syntax: vflag = VerifyGet
  4958.  
  4959.             Returns the current VERIFY setting of the  system.  This is NOT
  4960.      a read-after-write  test as some  think, but is  where DOS does  a CRC
  4961.      check of data just  written to make sure it is the same as that of the
  4962.      original data.  To CHANGE the VERIFY switch, use VerifySet (qv).  This
  4963.      routine returns 0 for OFF, non zero for ON.
  4964.  
  4965.  
  4966.  
  4967.              Name: VerifySet                Type: SUB
  4968.          Syntax: CALL VerifySet(vflag)
  4969.  
  4970.          Sets or resets the DOS VERIFY switch (see GetVerify for an explan-
  4971.      ation of  VERIFY).  Note  that if  you intend to  alter such a  system
  4972.      switch, it is good programming practice to restore it to its  original
  4973.      setting when  your program terminates,  this switch can  be determined
  4974.      via VerifyGet.  In  calling VerifySet, 0 turns VERIFY OFF,  1 turns it
  4975.      ON.  Example:
  4976.          CALL VerifyGet(0)
  4977.          CALL VerifySet(1)
  4978.  
  4979.  
  4980.  
  4981.              Name: VFName                   Type: FUNCTION
  4982.          Syntax: errc = VFName(fil$, DOSCode)
  4983.          VFName may also be called as ValidFileName
  4984.  
  4985.              VFNAME checks a string  you pass it to determine if the string
  4986.      indeed is capable  of being a valid  filename.   Pre  testing a string
  4987.      that you  may  have  gotten from end  user input, helps  avoid runtime
  4988.      errors  later on and  in the case  of novice end  users allows consid-
  4989.      erable feedback  from your program  on what is  wrong with a  filename
  4990.      typed in.
  4991.  
  4992.              The process is twofold - it tests  for characters such as ,[><
  4993.      and also attempts to open the file and  returns 2 error codes.  In the
  4994.      case  of the character  test, the FUNCTION  returns 0 (in  errc) if it
  4995.      finds  no  offending characters,  or the  ASCII  value of  any invalid
  4996.      filename character.   This allows  you to be  able to give  apparently
  4997.      intuitive feedback to users on valid filename characters.
  4998.  
  4999.              A second pass  is needed to test drive and path validity.  The
  5000.      colon and  backslash are not  tested as invalid  chars since they  ARE
  5001.      valid IF in the right spot.  To test this, VFNAME attempts  to open or
  5002.      create the  file thus returning  info on the  path, access and  if the
  5003.      file  already  exists.   Any DOS  feedback is  returned as  the formal
  5004.      parameter DOSCode.
  5005.          3 - Drive or path not found
  5006.          4 - No handle available ("Too Many Files")
  5007.          5 - Access denied (already opened on multi system)
  5008.          80 - file exists.
  5009.  
  5010.          NOTES:
  5011.          1) VFNAME does NOT actually create or open the file!  It just
  5012.             pre-tests for any possible runtime error in trying to do so.
  5013.          2) VFNAME requires DOS 3.x
  5014.  
  5015.                    Copyright (C) InfoSoft, 1986-1990, 1991               76
  5016.  
  5017.  
  5018.  
  5019.  
  5020.  
  5021.  
  5022.  
  5023.  
  5024.  
  5025.              Name: VidInfo                  Type: SUB
  5026.          Syntax: CALL VidInfo(NumRows, NumCols, Mode, Page, PgSize)
  5027.  
  5028.          With the advent  of the more  advanced video subsystems, the  pro-
  5029.      grammer can no longer  make certain assumptions such as number of rows
  5030.      or  columns.   VidInfo  attempts  to  return much  of  the information
  5031.      available on the current settings:
  5032.          NumRows - The number of rows in the current mode.
  5033.          NumCols - The number of video columns.
  5034.          Mode    -  The Video mode.  This has little to do with the        
  5035.                    BASIC SCREEN statement - it is the DOS video mode.
  5036.          Page    - The current active page.
  5037.          PgSize  - The size in bytes of the active page.
  5038.          See also VidType, VTypeSet and VTypeClr
  5039.  
  5040.  
  5041.  
  5042.                            
  5043.  
  5044.              Name: VidOff/VidOn             Type: SUB
  5045.          Syntax: CALL VidOn
  5046.  
  5047.              Similar to a screen saver program,  this routine will turn off
  5048.      any monitor (tested  on CGA, EGA, MDA  and VGA).  If a  timing loop in
  5049.      your long running program senses no activity  for x minutes, a call to
  5050.      VIDOFF will  turn off the display, then once you sense activity again,
  5051.      VIDON restores the display.
  5052.  
  5053.          Note: VidOn /  VidOff will only toggle  the video output on  a VGA
  5054.      system equipped  with both  a VGA  adapter AND  a VGA  monitor.   Some
  5055.      'super' VGA cards that  can drive any monitor may not  respond to this
  5056.      depending on what mode or type of emulation they are performing.
  5057.  
  5058.  
  5059.  
  5060.  
  5061.              Name: VidType                  Type: FUNCTION
  5062.          Syntax: crt = VidType
  5063.  
  5064.          No routine can  tell you the  type of display  attcahed to a  com-
  5065.      puter, but  routines such as  VidType CAN tell  you the type  of video
  5066.      display card installed.   As such, VidType returns an  integer code to
  5067.      identify the active video card and/or mode:
  5068.  
  5069.      0 = MONO                 4 = EGA Mono             8 = VGA Mono
  5070.      1 = Herc, Herc Plus      5 = EGA Color            9 = VGA Color
  5071.      2 = Herc Incolor         6 = MCGA Mono
  5072.      3 = CGA                  7 = MCGA Color
  5073.  
  5074.          Note that on multiple display systems, the active display is
  5075.      identified on EGA/VGA systems, while the  primary one is identified on
  5076.      CGA/Mono  multiple  display systems.    Also, some  "Super  VGA" cards
  5077.      connected to Multi Synch monitors, may  identify the Multi Sych system
  5078.      as an EGA.   This is dependant on the BIOS  compatibility of the card.
  5079.      See also VTypeSet and VTypeClr
  5080.  
  5081.                    Copyright (C) InfoSoft, 1986-1990, 1991               77
  5082.  
  5083.  
  5084.  
  5085.  
  5086.  
  5087.  
  5088.  
  5089.  
  5090.  
  5091.              Name: VidPageCsr               Type: SUB
  5092.          Syntax: CALL VidPageCsr(page, row, col)
  5093.  
  5094.          This fetches  the correct row, column coordinates  for a requested
  5095.      video  page.  No  error checking  is done for  a VALID page,  but when
  5096.      called from  a loop, it can quickly fetch  the cursor location for any
  5097.      and all pages. Example: Get Cursor locations into array
  5098.          FOR x = 1 to MaxPages
  5099.              CALL VidPageCsr(x, Csr(x,1), Csr(x,2) )
  5100.          NEXT x
  5101.  
  5102.  
  5103.                         
  5104.              Name: VLabelGet/VLabelSet      Type: FUNCTION
  5105.          Syntax: MyLabel$ = VLabelGet$
  5106.                  errc = VLabelSet(NewVLabel$)
  5107.  
  5108.          Allows you to get or set the disk volume  label.  The maximum size
  5109.      allowed for a  label is 11  characters.  VLabelSet  will only use  the
  5110.      first 11 of whatever you pass (pass  SPACE$(11) to clear the name).  A
  5111.      return code of -1 indicates and error.
  5112.  
  5113.  
  5114.  
  5115.  
  5116.              Name: VTypeSet/VTypeClr        Type: FUNCTION and SUB
  5117.          Syntax: errc = VTypeSet(ColorType, TraceFlag)     (Function)
  5118.                  CALL VTypeClr                             (SUB)
  5119.  
  5120.          These sub  programs allow you to override  or tailor the video sub
  5121.      system detection code  used internally  by virtually all  of the  GLib
  5122.      video routines (Painter, Windows, Boxes, QPrint etc).  At times it may
  5123.      be desirable override  the default  systems detected.   For example  a
  5124.      very high quality CGA  may not need video retrace performed  (ie 'snow
  5125.      removal'), VTypeSet would  allow you  to instruct most  all video  sub
  5126.      programs to  skip such  retrace checking.   Of course,  in this  case,
  5127.      there is  no way for your code  to tell if the snow  removal is needed
  5128.      without asking the end user.  
  5129.          Another example  is in odd video  cards such as a  "CGA Emulator":
  5130.      in using VTypeSet,  you can force  output to the  MONO or COLOR  video
  5131.      segments as need  by these.  Finally, the very high-res EGA cards used
  5132.      on early Model  80's for ACAD and  such _are_ color systems,  yet they
  5133.      return a code  indicating a MONO  sub system (on  purpose I am  told).
  5134.      Using VTypeSet allows you to force output to the color segment.
  5135.  
  5136.       Parameters:
  5137.  
  5138.       ColorType: 0 causes output to the Mono video segment;
  5139.                  1 forces output to the color segment
  5140.                  Any other value causes an  error to be returned.
  5141.       TraceFlag: 0 eliminates video retrace checking ("snow removal")      
  5142.                  1 forces it to be used regardless of the video sub system 
  5143.  
  5144.                  See Note below
  5145.  
  5146.  
  5147.                    Copyright (C) InfoSoft, 1986-1990, 1991               78
  5148.  
  5149.  
  5150.  
  5151.  
  5152.  
  5153.  
  5154.  
  5155.          VTypeClr  clears the  overrides  that you  set  with VTypeSet  and
  5156.      instructs GLib video sub programs to act based on the video sub system
  5157.      detected by it's internal detection routines.
  5158.  
  5159.          Notes:
  5160.      1.)   Since VTypeSet overrides the defaults, no error or integrity
  5161.            checking performed.  Setting the TraceFlag (1) and the ColorType
  5162.            to MONO (0) may  hang the system for a variety of reasons.  The 
  5163.            TraceFlag should only be set when the ColorType  is set to Color
  5164.            (1) _AND_  there is indeed a color subsystem installed  and     
  5165.            active.  Setting the TraceFlag with  a EGA or VGA system will   
  5166.            cause it to hang as there is never a high or low return from the
  5167.            retrace port - it is non-existant!
  5168.  
  5169.        
  5170.      2.)    Wise use of this can also be used to slow down the grow effect 
  5171.            of WINDOWS  and possibly provide a method of adjusting the GROW 
  5172.            factor.  By setting the TraceFlag to 1 (on  CGA systems) and    
  5173.            forcing video retrace, just  the right amount of delay may be   
  5174.            added to the growing of the WINDOWS. 
  5175.  
  5176.  
  5177.  
  5178.  
  5179.  
  5180.  
  5181.  
  5182.  
  5183.  
  5184.  
  5185.  
  5186.  
  5187.  
  5188.  
  5189.  
  5190.  
  5191.  
  5192.  
  5193.  
  5194.  
  5195.  
  5196.  
  5197.  
  5198.  
  5199.  
  5200.  
  5201.  
  5202.  
  5203.  
  5204.  
  5205.  
  5206.  
  5207.  
  5208.  
  5209.  
  5210.  
  5211.  
  5212.  
  5213.                    Copyright (C) InfoSoft, 1986-1990, 1991               79
  5214.  
  5215.  
  5216.  
  5217.  
  5218.  
  5219.  
  5220.  
  5221.              Name: Windows                  Type: SUB
  5222.         Syntax: CALL Windows(TR, LC, BR, RC, SFX, Grow,  Frame, Attr,_     
  5223.                               label$)
  5224.  
  5225.             An extensive  windowing routine,  allows you  to fully  control
  5226.      frames, sound, color and  grow effect.  The routine  requires numerous
  5227.      arguments passed.   Be warned that NO error checking takes place as to
  5228.      accurate or  misplaced coordinates  - really  far out  coordinates can
  5229.      lock up the machine  (such as locating the bottom of  the window ABOVE
  5230.      the top etc...).
  5231.          Frames:  WINDOWS comes with virtually an unlimited number of frame
  5232.                 styles with the five most common 'built in':
  5233.                  0 - Spaces used / no frame
  5234.                  1 - Double Lines Horizontal  / Double Lines Vertical
  5235.                  2 - Double Lines Horizontal  / Single Lines Vertical
  5236.                  3 - Single Lines Horizontal  / Single Lines Vertical
  5237.                  4 - Single Lines Horizontal  / Double Lines Vertical
  5238.  
  5239.           Invoking WINDOWS with the frame style set to 5 tells WINDOWS
  5240.           to use the user defined character set for the frame as defined
  5241.           by the WSetUDef sub program (qv).  An unrecognized frame style
  5242.           code such as anything over 5 or 5 if there is no user defined
  5243.           frame style defined, will default to type 0 - spaces/no frame.
  5244.  
  5245.      Grow:    By setting the GROW parameter to ZERO, the window simply     
  5246.              appears on the screen.  Non Zero indicates you  want a growing
  5247.              effect and controls the grow speed: the larger the number, the
  5248.              slower the growing.  Other grow effect factors:             
  5249.                  o Video Sub system:  This is more a factor than the CPU   
  5250.                    type or speed: A 25 MHz 386 with a CGA will need about
  5251.                    the same grow factor as a 6 Mhz 286 and a 8088 PC also
  5252.                    with a CGA will require a similar GROW factor, more so
  5253.                    than if it has a VGA.
  5254.                  o WINDOW Size and Shape.  A tall, but  narrow window      
  5255.                    may need a different delay value than a very wide but   
  5256.                    short one.
  5257.                  o  Each increment of one invokes  a delay of 1 clock tick.
  5258.                    This may not sound like much, and indeed in the grand   
  5259.                    scheme of things it is not, but  in the context of 18 to
  5260.                    24 redrawings of  a window it can be a lot.  Our testing
  5261.                    on VGA and fast 286 systems showed that GROW factor
  5262.                    values of 1, 2 and 3 were plenty to slow down the delay
  5263.                    a speed at which it can be perceived.  Too long of a
  5264.                    delay makes the CHIRP sound  incongruent and the growing
  5265.                    look 'funny'.
  5266.  
  5267.          Other Parameters:
  5268.          TR    - Top row of window to be displayed.
  5269.          LC    - Left border of window to be displayed.
  5270.          BR    - Bottom row of window to be displayed.
  5271.          RC    - Right border of window.
  5272.          SFX   - Sound effects toggle, 0=OFF 1=ON
  5273.          Grow  - Grow switch, 0 = No grow, Non Zero = Grow Speed
  5274.          Frame - Style of frame to use for the window
  5275.          Attr  - Attribute of window (See also MakeAttr)
  5276.          Label$- Label to center across the top of the window, for no label
  5277.                  use ""
  5278.  
  5279.                    Copyright (C) InfoSoft, 1986-1990, 1991               80
  5280.  
  5281.  
  5282.  
  5283.  
  5284.  
  5285.  
  5286.  
  5287.          Example:
  5288.          tr=2 : lc=2 
  5289.          br=5 : rc=79 
  5290.          sfx=1 : gro=1 : frame=1
  5291.          attr=78 
  5292.          label$=" A long window across the top of the screen "
  5293.  
  5294.          CALL Windows(tr, lc, br, rc, sfx, gro, frame, attr, l$)
  5295.          or
  5296.          CALL windows(2, 2, 5, 45, 0, 1, 4, 64, "")
  5297.          Puts a window to the screen  from 2,2 to 5,79, with a chirp  sound
  5298.      effect, with a double / double line  frame with a yellow foreground on
  5299.      a red background.
  5300.  
  5301.          Other sub programs that  control or add to WINDOWS or  can be used
  5302.      with it  include:   WShadow, MakeAttr,  Chirp,  BufCalc, VTypeSet  and
  5303.      SaveScrn
  5304.  
  5305.  
  5306.  
  5307.  
  5308.              Name: WSetUDef                 Type: SUB
  5309.          Syntax: CALL WSetUdef(TL, TR, BL, BR, VChar, HChar)
  5310.  
  5311.          WINDOWS has 5 built  in, or default frame styles, however  in cer-
  5312.      tain situations,  you may want to define your  own via WSetUDef.  Once
  5313.      defined they may  be used over and  over; that is,  you need not  call
  5314.      WSetUDef over and  over to set the  same User Defined frame  style for
  5315.      each call to WINDOWS.  The User Defined type can be changed later with
  5316.      another call  to WSetUDef.   The parameters  sent to WSetUDef  are in-
  5317.      tegers  representing the ASCII  value of the character  to use for the
  5318.      Top Left corner,  Top Right corner,  Bottom Left corner, Bottom  Right
  5319.      corner, Vertical character and Horizontal character respectively.
  5320.  
  5321.          Example:
  5322.          ' Set Window frames to "?"
  5323.          CALL WSetUDef(63, 63, 63, 63, 63, 63)
  5324.          ..
  5325.          ..
  5326.          ' make growing window, with no sound with "?????" frame style
  5327.          CALL Windows(5, 5, 18, 45, 0, 1, 5, 78, " Test ")
  5328.  
  5329.  
  5330.          ' change  user defined box characters to 'test' on  frame style   
  5331.          '   (+-|):
  5332.          CALL WsetUDef(43, 43, 43, 43, 124, 45)
  5333.          ..
  5334.          ..
  5335.          CALL Windows(5, 5, 18, 45, 0, 1, 5, 78, "Text")
  5336.  
  5337.  
  5338.  
  5339.  
  5340.  
  5341.  
  5342.  
  5343.  
  5344.  
  5345.                    Copyright (C) InfoSoft, 1986-1990, 1991               81
  5346.  
  5347.  
  5348.  
  5349.  
  5350.  
  5351.  
  5352.  
  5353.              Name: WShadow                  Type: SUB
  5354.          Syntax: CALL WShadow(Flag)
  5355.  
  5356.          This sets a global flag to indicate to the Windows routine whether
  5357.      or not it is  to draw the window with a shadow  or '3-D' effect around
  5358.      it.  By  'global', we mean all  future calls to Windows,  whether from
  5359.      your  main code module or from inside a  sub, will respect the setting
  5360.      of the flag.
  5361.  
  5362.          By making this shadowing effect a separate call, we avoid adding a
  5363.      parameter to the  Window call that  invalidates thousands of lines  of
  5364.      code that are already written as documented above.  Shadow Parameter:
  5365.            0 = Off - no shadowing
  5366.            1 =  Shadowing ON - Place shadow on bottom and right side       
  5367.                       of window.
  5368.           -1 = Shadowing  ON - Place shadow on bottom and left side of     
  5369.                         window.
  5370.  
  5371.      This shadow effect basically washes out  the underlying colors - not a
  5372.      simple string of spaces in color 0 that others will try to tell you is
  5373.      a shadow.  If  you hold a paper half-in and half-out  of a shadow, you
  5374.      can still  see the  portion in  the shade  - just  the tones  and hues
  5375.      change!
  5376.  
  5377.          The size of  the window frame  is unaffected  by WShadow, but  one
  5378.      more screen row  and one more column  is altered, and should  be taken
  5379.      into consideration when saving a portion of the screen   (ie:
  5380.      SaveWindow).
  5381.  
  5382.          Once set, the  shadow is automatically  displayed with every  sub-
  5383.      sequent call to  Windows.  If you always  use a shadow and  want it on
  5384.      the right, 'CALL WShadow(1)' is all you need to add to your code - all
  5385.      Window calls after that will have a shadow on the right.
  5386.  
  5387.          Thru the  course of your program,  WShadow can be changed  to move
  5388.      the shadow  to the other side or  halt it and reactivate  it, but only
  5389.      future calls to Windows are affected.
  5390.  
  5391.  
  5392.  
  5393.  
  5394.  
  5395.  
  5396.  
  5397.  
  5398.  
  5399.  
  5400.  
  5401.  
  5402.  
  5403.  
  5404.  
  5405.  
  5406.  
  5407.  
  5408.  
  5409.  
  5410.  
  5411.                    Copyright (C) InfoSoft, 1986-1990, 1991               82
  5412.  
  5413.  
  5414.  
  5415.  
  5416.  
  5417.  
  5418.  
  5419.          Acknowledgements
  5420.  
  5421.          Advanced MS DOS Programming, MS-DOS Functions and IBM ROM BIOS 
  5422.                 all by Ray Duncan
  5423.  
  5424.          Norton Guides For Assembler
  5425.  
  5426.          Programmers Guide to PC and PS/2 Video Systems by Richard Wilton
  5427.  
  5428.          Programming Problem Solver Handbook by Robert Jordain
  5429.  
  5430.          Assembly Language Subroutines by Leo J Scanlon
  5431.  
  5432.          Interrupt List - A file of undocumented or poorly documented
  5433.                     interrupts found on BBSes everywhere.
  5434.  
  5435.          MS-DOS Encyclopedia published by Microsoft Press, edited by
  5436.                Ray Duncan
  5437.  
  5438.          System BIOS for IBM PC/XT/AT computers and compatibles
  5439.                by Phoenix Technologies
  5440.  
  5441.  
  5442.          The basic timekeeping function and framework  of CLOCK is based on
  5443.      CLOCK.ASM PC Magazine  Vol 6 No 17.   Our enhancements include  the 12
  5444.      hour  display  format, label,  secondary  timing  loop to  adjust  the
  5445.      accuracy and the tone that sounds on the hour and half hour.
  5446.  
  5447.          QCALC  is  based on  a Floating  Point  Calculator in  'C' (author
  5448.      unknown) and CALC.COM (A TSR pop up calculator)  from Vol 7 No 6 of PC
  5449.      Magazine.  Our modifications include  making it locatable, the display
  5450.      appearance,  the blinking buttons  and speed parameter,  and making it
  5451.      callable from "C" or "QB" and returning a long
  5452.      integer to either.
  5453.  
  5454.          Finally, if you  are interested in  ASM level programming or  just
  5455.      plain tinkering, the Microsoft KnowledgeBase is invaluable.  When many
  5456.      of the normal interface items changed in QB4, they are not  completely
  5457.      covered in  the Mixed  Language Programming  Guide, but many  extended
  5458.      explanations and examples  are in the KnowledgeBase.   Information for
  5459.      passing Fixed  Length String arrays  as well  as string arrays  to ASM
  5460.      routines that is radically different  in QB4 and QBX (BASIC PDS),  for
  5461.      instance, that made DirA and DIRF possible came from there.
  5462.  
  5463.  
  5464.  
  5465.  
  5466.  
  5467.  
  5468.  
  5469.  
  5470.  
  5471.  
  5472.  
  5473.  
  5474.  
  5475.  
  5476.  
  5477.                    Copyright (C) InfoSoft, 1986-1990, 1991               83
  5478.  
  5479.  
  5480.